完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
最近在弄单片机的硬件i2c,tuner小板的硬件i2c有两个,i2c0和i2c1。但是80c51f340的i2c和他们又有区别,所以我将其对接的时候用i2c0写没问题,但是i2c0读的时候少了一个nack的操作(stop反而有,费解),导致每次读完操作以后下次读或者写发chipid的时候都会nack。现在连i2c1发完chipid给个nack都死机了,我真的无力了,求助,下面是时序图和程序
C8051F340的时序是 write: start| chipid(7:1)+write(写0) | Ack | address(7:0) | Ack | data(7:0) | Ack | stop; read: start | chipid(7:1)+write(写0) | Ack | address(7:0) | Ack | Restart | chipid(7:1)+read(写1) | Ack | data(7:0) | Nack; start | chipid(7:1)+write(写0) | Ack | address(7:0) | Ack | Restart | chipid(7:1)+read(写1) | Ack | data1(7:0) | Ack | data2(7:0) | Ack |……| dataN(7:0) | Nack; 而5158的是这样的 I2c0: I2c1: #include "c8051f340.h" #define uchar unsigned char #define uint unsigned int #define ulong unsigned long #define chip5158_I2C0 0xC4 //Device address for slave 5158_chip in i2c0 #define chip5158_I2C1 0xC2 //Device address for slave 5158_chip in i2c1 #define SYSCLS 12000000 //#define SMB_FQ 50000 //Target SCL clock rate #define WRITE 0x00 //SMBUS WRITE command #define READ 0x01 //SMBUS READ command typedef struct { uchar TARGET; //从地址(读或写时要先写入它的值) uchar SMB_RW; }I2C_DATA; void Wait(int x) { while(x--); } void SMBUS_Init() { SMB0CF = 0x5D; // Use timer1 overflows as SMBus clock // source; // Disable slave mode; // Enable setup & hold time extensions; // Enable SMBus Free timeout detect; // Enable SCL low timeout detect; SMB0CF &= ~0x80; SMB0CF |= 0x80; //Enable SMBUS EIE1 &= 0xFE; SMB0CN &= 0xCC; //Init SMB0CN } void Timer1_Init(ulong SMB_FQ) { // uchar SCALE; if ((SYSCLS/SMB_FQ/3) < 255) { // SCALE = 1; CKCON |= 0x08 ; } else if ((SYSCLS/SMB_FQ/3/4) < 255)//使用4分频 { // SCALE = 4; CKCON |= 0x01; CKCON &= ~0x0A; } else if ((SYSCLS/SMB_FQ/3/8) < 255)//使用8分频 { // SCALE = 8; CKCON |= 0x03; CKCON &= ~0x08; } else if ((SYSCLS/SMB_FQ/3/12) < 255)//使用12分频 { // SCALE = 12; CKCON |= 0x03; CKCON &= ~0x0B; } else if ((SYSCLS/SMB_FQ/3/48) < 255)//使用48分频 { // SCALE = 48; CKCON |= 0x03; CKCON &= ~0x09; } TMOD = 0x20; TH1 = 256 -(SYSCLS/SMB_FQ/3); TL1 = TH1; TR1 = 1; } #if 0 void Timer3_Init() { TMR3CN = 0x00; //16位时钟,低字节中断 CKCON &= ~0x40; //使用12分频时钟信号 TMR3RLL = -(SYSCLS/12/40); TMR3L = TMR3RLL; //25ms之后时钟3执行溢出重载 EIE1 |= 0x80; //时钟3中断使能 TMR3CN |= 0x04; //打开时钟3 } #endif void PORT_Init() { 0MDIN = 0xff; 0MDOUT = 0x00; 0SKIP = 0x00; XBR0 = 0x04; XBR1 = 0x40; 0 = 0xFF; } void Send_Start(void) { STA = 1; SI = 0; } void Send_Stop(void) { STO = 1; SI = 0; } void Send_Addr(uchar target_addr,uchar smb_rw) { uchar dat; dat = target_addr; dat &= 0xFE; dat |= smb_rw; SMB0DAT = dat; STA = 0; SI = 0; } void Send_Data(uchar dat) { SMB0DAT = dat; SI = 0; } void Receive_Data() { uchar dat; dat = SMB0DAT; ACK = 0; SI = 0; } void Rec_Last_Data() { uchar dat; dat = SMB0DAT; ACK = 1; SI = 0; } uchar get_SMBDAT() { return SMB0DAT; } void Reset_I2C(void) { SMB0CF &= ~0x80; Wait(50); SMB0CF |= 0x80; //重启SMBUS SMB0CN &= 0xCC; } uchar Return_I2C_Status() { return SI; } void I2c0_Write(uchar dest_addr,uint src_data) { // I2C_DATA temp; // SPI0CN &= ~0x01; // temp.TARGET = chip5158_I2C0; // temp.SMB_RW = WRITE; uchar src_buf[2]; src_buf[0] = src_data>>8; src_buf[1] = src_data; Send_Start(); while(!Return_I2C_Status()); Send_Addr(chip5158_I2C0,WRITE); while(!Return_I2C_Status()); Send_Data(dest_addr); while(!Return_I2C_Status()); Send_Data(src_buf[0]); while(!Return_I2C_Status()); Send_Data(src_buf[1]); // STO = 1; while(!Return_I2C_Status()); Send_Stop(); // while(!Return_I2C_Status()); Reset_I2C(); // SPI0CN |= 0x01; } void I2c0_Read(uchar *dest_buf,uchar src_addr) { // I2C_DATA temp; // SPI0CN &= ~0x01; // temp.TARGET = chip5158_I2C0; // temp.SMB_RW = WRITE; Send_Start(); while(!Return_I2C_Status()); Send_Addr(chip5158_I2C0,WRITE); while(!Return_I2C_Status()); Send_Data(src_addr); while(!Return_I2C_Status()); Send_Start(); while(!Return_I2C_Status()); Send_Addr(chip5158_I2C0,READ); while(!Return_I2C_Status()); Receive_Data(); while(!Return_I2C_Status()); dest_buf[0] = get_SMBDAT(); Rec_Last_Data(); while(!Return_I2C_Status()); dest_buf[1] = get_SMBDAT(); // ACK = 1; // ACK = 1; // ACK = 1; Send_Stop(); // while(!Return_I2C_Status()); Reset_I2C(); // SPI0CN |= 0x01; } void I2c1_Readbyte(uchar *dest_buf,ulong src_addr) { uchar temp[4]; temp[0] = (uchar)(src_addr<<1); temp[0] |= 0x01; //get ADDR[6:0],1; temp[1] = (uchar)(src_addr>>16);//get ADDR[23:16]; temp[2] = (uchar)(src_addr>>24);//get ADDR[31:24]; temp[3] = (uchar)(src_addr>>7); //get ADDR[14:7]; Send_Start(); while(!Return_I2C_Status()); Send_Addr(chip5158_I2C1,WRITE); while(!Return_I2C_Status()); Send_Data(temp[0]); while(!Return_I2C_Status()); Send_Data(temp[1]); while(!Return_I2C_Status()); Send_Data(temp[2]); while(!Return_I2C_Status()); Send_Data(temp[3]); while(!Return_I2C_Status()); Send_Start(); while(!Return_I2C_Status()); Send_Addr(chip5158_I2C0,READ); while(!Return_I2C_Status()); Receive_Data(); while(!Return_I2C_Status()); dest_buf[0] = get_SMBDAT(); Rec_Last_Data(); while(!Return_I2C_Status()); dest_buf[1] = get_SMBDAT(); Send_Stop(); while(!Return_I2C_Status()); Reset_I2C(); } void I2c1_Writebyte(ulong dest_addr,uint src_data) { uchar temp[4],src_buf[2]; temp[0] = (uchar)(dest_addr<<1); temp[0] |= 0x01; //get ADDR[6:0],1; temp[1] = (uchar)(dest_addr>>16);//get ADDR[23:16]; temp[2] = (uchar)(dest_addr>>24);//get ADDR[31:24]; temp[3] = (uchar)(dest_addr>>7); //get ADDR[14:7]; src_buf[0] = src_data; src_buf[1] = src_data>>8; Send_Start(); while(!Return_I2C_Status()); Send_Addr(chip5158_I2C1,WRITE); while(!Return_I2C_Status()); Send_Data(temp[0]); while(!Return_I2C_Status()); Send_Data(temp[1]); while(!Return_I2C_Status()); Send_Data(temp[2]); while(!Return_I2C_Status()); Send_Data(temp[3]); while(!Return_I2C_Status()); Send_Data(src_buf[0]); while(!Return_I2C_Status()); Send_Data(src_buf[1]); while(!Return_I2C_Status()); Send_Stop(); // while(!Return_I2C_Status()); Reset_I2C(); } void I2c1_Start(void) { // uchar buff[2]; // I2c0_Write(0xea,0xccda); // I2c0_Write(0xea,0x69c4); // I2c0_Write(0xea,0xffff); // I2c0_Read(buff,0xea); // I2c0_Read(buff,0xea); // I2c0_Read(buff,0xea); #if 1 I2c0_Write(0xe2,0xccda); // I2c0_Read(buff,0xe2); I2c0_Write(0xe4,0x69c4); // I2c0_Read(buff,0xe4); I2c0_Write(0xf6,0x0000); // I2c0_Read(buff,0xf6); I2c0_Write(0xf2,0x0000); // I2c0_Read(buff,0xf2); I2c0_Write(0xf2,0x0001); //dsp reset // I2c0_Read(buff,0xf2); #endif Wait(10); I2c0_Write(0xea,0x8000); // I2c0_Read(buff,0xea); Wait(10); } #if 0 void I2c1_Stop() { ; } #endif void main(void) { // char in_buff[9]; // char out_buff[8]="ABCDEFGH"; // uchar in_buff0[2]; uchar in_buff1[2]; uint out_data0=0x4142; uint out_data1=0x4143; CA0MD &= ~0x40; //stop WDT OSCICN |= 0x03; //SYSCLK为内部高频正当期输出 RSTSRC = 0x04; //使能丢失时钟监测器 ORT_Init(); Timer1_Init(30000);//Sumbus's frequence // Timer3_Init(); SMBUS_Init(); EA = 1; while(1) { // I2c0_Read(in_buff,0xe0); //read 2byte from 0xe0 // I2c0_Write(0xE2,out_data0); // I2c0_Read(in_buff0,0xE2); I2c1_Start(); I2c1_Writebyte(0x13145210,out_data1); I2c1_Readbyte(in_buff1,0x13145210); // I2c1_Stop(); } } |
|
相关推荐
7个回答
|
|
我去,原来程序是对的,只是因为clock太快了!!!所以不给反应啊.............谢谢了~~
|
|
|
|
@发烧友,原子哥,求助啊,i2c0读的时候差一个clock,最好我回nack的时候没有clock来,只有最后stop的时候有响应,这样的话对应就会出错,能不能控制clock,让它多发一个clock信号,把我的nack采集进去啊。还有,i2c1现在写的时候写入chipid就挂了..............头疼了两天了,为这个.........真的求助
|
|
|
|
用模拟的路过。。。
|
|
|
|
模拟的我之前用过了,没有硬件I2C来的快,我想用硬件i2c来实现,现在问题得不到解决啊,整个人都不好了...........
|
|
|
|
硬件的话不是配置好之后自己通讯的么,怎么还要多发一个clock呢
|
|
|
|
clock应该是自己发的啊,我改了一下,read的时候还是少一个stop,刚才那两个read都有问题
void I2c0_Read(uchar *dest_buf,uchar src_addr) { //I2C_DATA temp; //SPI0CN &= ~0x01; //temp.TARGET = chip5158_I2C0; //temp.SMB_RW = WRITE; Send_Start(); while(!Return_I2C_Status()); Send_Addr(chip5158_I2C0,WRITE); while(!Return_I2C_Status()); Send_Data(src_addr); while(!Return_I2C_Status()); Send_Start(); while(!Return_I2C_Status()); Send_Addr(chip5158_I2C0,READ); while(!Return_I2C_Status()); Clear_SI(); while(!Return_I2C_Status()); dest_buf[0] = Receive_Data(); while(!Return_I2C_Status()); dest_buf[1] = Rec_Last_Data(); while(!Return_I2C_Status()); //Send_Stop(); Reset_I2C(); //SPI0CN |= 0x01; } stop应该是5158tuner发给我的,可是不知道为什么没有,我用中断来写的时候都有的,换成现在这种写法就不行了 |
|
|
|
IIC里面,单片机永远都是主机,不管发送还是读取,停止信号是主机发出的,你不发出stop信号怎么产生,从设备只是被动接收
|
|
|
|
只有小组成员才能发言,加入小组>>
3288 浏览 9 评论
2962 浏览 16 评论
3465 浏览 1 评论
9010 浏览 16 评论
4054 浏览 18 评论
1130浏览 3评论
579浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
573浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2306浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1866浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-30 19:50 , Processed in 1.535125 second(s), Total 92, Slave 73 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号