iic 通讯,读写异常,麻烦有高手可以帮忙看看,谢谢!!

2019-07-19 20:44发布

头文件如下:
 #ifndef __IIC_H__
#define __IIC_H__ #include "stm8l15x_gpio.h" #define SCL_OUT_INIT()    GPIO_Init(GPIOC,GPIO_Pin_1,GPIO_Mode_Out_OD_Low_Fast)
#define SCL_OUT_HIGH()    GPIO_WriteBit(GPIOC,GPIO_Pin_1,SET)
#define SCL_OUT_LOW()     GPIO_WriteBit(GPIOC,GPIO_Pin_1,RESET) #define SDA_OUT_INIT()    GPIO_Init(GPIOC,GPIO_Pin_0,GPIO_Mode_Out_OD_Low_Fast)
#define SDA_OUT_HIGH()    GPIO_WriteBit(GPIOC,GPIO_Pin_0,SET)
#define SDA_OUT_LOW()     GPIO_WriteBit(GPIOC,GPIO_Pin_0,RESET) #define SDA_IN_INIT()     GPIO_Init(GPIOC,GPIO_Pin_0,GPIO_Mode_In_FL_No_IT)
#define SDA_IN_DATA()     GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_0)
#define IIC_HIGH  0x80
#define IIC_LOW  0 extern void iic_init();
extern  void iic_single_byte_write(unsigned char Daddr, unsigned char addr, unsigned char data);
extern unsigned char iic_single_byte_read(unsigned char Daddr, unsigned char addr);
#endif /* __IIC_H__ */


函数定义如下:

#include "IIC.h"
extern void delay(uint32_t);
//IIC初始化函数
void iic_init(){
        //初始化引脚为输出
 SCL_OUT_INIT();
 SDA_OUT_INIT();
        delay(20);
        //初始化状态为高电平
 SCL_OUT_HIGH();
 SDA_OUT_HIGH();
        delay(20);
} //IIC起始信号
void iic_start() {
    SCL_OUT_INIT();
 SDA_OUT_INIT();         //SDA = 1
 SDA_OUT_HIGH();
 delay(2);         //SCL = 1
 SCL_OUT_HIGH();
 delay(2);         //SDA = 0
 SDA_OUT_LOW();
 delay(2);          //SCL = 0
// SCL_OUT_LOW();
// delay(2);
} //IIC终止信号
void iic_stop() {
   SCL_OUT_INIT();
 SDA_OUT_INIT();
        //SDA = 0
 SDA_OUT_LOW();
 delay(2);         //SCL = 1
 SCL_OUT_HIGH();
 delay(2);         //SDA = 1
 SDA_OUT_HIGH();
 delay(2);
} //IIC应答信号
void iic_respons(){
 
 unsigned char i=0;  SCL_OUT_INIT();
// SDA_OUT_INIT();
 
    //SCL = 1
 SCL_OUT_HIGH();
 delay(2);     //SDA初始化为输入
 SDA_IN_INIT();  while((SDA_IN_DATA()==1)&& (i<250))i++;
 
 SDA_OUT_INIT();
 
    //SCL = 0
 SCL_OUT_LOW();
 delay(2); } //void respons()  //应答
//{ 
//uchar i; 
//scl = 1; 
//delay(); 
//while((sda==1)&&(i<250))i++;
//scl = 0; 
//delay();
//} //void NoRespons()//不应答
//{ sda=1; 
//delay();
//scl=1;
//delay();
//scl=0;
//delay();
//}
void iic_no_respons(){
 SCL_OUT_INIT();
 SDA_OUT_INIT();
  //SDA=1
 SDA_OUT_HIGH();
 delay(2);
 
    //SCL = 1
 SCL_OUT_HIGH();
 delay(2);
 
    //SCL = 0
  SCL_OUT_LOW();
 delay(2); }
void iic_write_byte(unsigned char data) {
 unsigned char i, temp;  SCL_OUT_INIT();
 SDA_OUT_INIT();
 
 for (i = 0; i < 8; i++) {
  temp = data;
  temp = temp & 0x80;
  
  SCL_OUT_LOW();
  delay(2);
  
  if(IIC_HIGH == temp) {
   SDA_OUT_HIGH();
  }
  else {
   SDA_OUT_LOW();
  }
  delay(2);
  
  SCL_OUT_HIGH();
  delay(2);   data = data<<1;
 }
        SCL_OUT_LOW();
       delay(2);
       SDA_OUT_HIGH();
        delay(2); }
unsigned char iic_read_byte() {
 unsigned char i, temp=0, data=0;  SCL_OUT_INIT();
 SDA_OUT_INIT();
 
 SCL_OUT_LOW();
 delay(2);
 SDA_OUT_HIGH();
 delay(2);     //SDA初始化为输入
 SDA_IN_INIT();
    delay(2);
 
 for (i = 0; i < 8; i++) {
  SCL_OUT_HIGH();
  delay(5);
  
  temp = SDA_IN_DATA();
  data = (data << 1) | temp;
  
  SCL_OUT_LOW();
  delay(5);
 }     //SDA重新初始化为输出
 SDA_OUT_INIT();
   delay(5);  
 return data;
} void iic_single_byte_write(unsigned char Daddr, unsigned char addr, unsigned char data){
   iic_start();    iic_write_byte(Daddr);
   iic_respons();    iic_write_byte(addr);
   iic_respons();    iic_write_byte(data);
   iic_respons();    iic_stop();
}
unsigned char iic_single_byte_read(unsigned char Daddr, unsigned char addr){
   unsigned char data;    iic_start();
   iic_write_byte(Daddr);
   iic_respons();    iic_write_byte(addr);
   iic_respons();    iic_start();
   iic_write_byte(Daddr+1);
   iic_respons();    data = iic_read_byte();
   iic_no_respons();    iic_stop();    return data;
}

当前问题是:
读取数据部分非0xff,且固定,应该可以判定读正常;
写新数据后读出的数据仍为写入前的数据,
波形均正常。麻烦有高手帮忙解决下,谢谢!!
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
17条回答
magni
1楼-- · 2019-07-21 03:28
回复【7楼】Badu_Space:
---------------------------------
感谢花时间耐心回复。
完全按照你的修改意见修改完毕之后,读出以及写新数据后读出的情况和修改前基本一样。
不同点在于:
1:修改前绝大部分读出为0xff, 修改后为0xfe
2:其他数据也有类是变化。
八度空间
2楼-- · 2019-07-21 04:59
 精彩回答 2  元偷偷看……
magni
3楼-- · 2019-07-21 10:20
回复【9楼】Badu_Space:
回复【8楼】magni:---------------------------------我的IIC驱动就是这样的,现在已经用在项目上了,呵呵我的代码比你的简洁
---------------------------------
谢谢你的回复,
问题现在基本搞定了。
我用的是AT24C128,需要写入的地址需要注意。
即主要的问题在以下两个函数中:
void iic_single_byte_write(unsigned char Daddr, 【unsigned char addr】 unsigned char data){}

unsigned char iic_single_byte_read(unsigned char Daddr, 【unsigned int addr】){}

其他函数暂时还没有发现问题。

现在的新问题是写入的数据读出之后被左移了一位,即乘以了2,具体原因还在调查中。
magni
4楼-- · 2019-07-21 13:49
temp = SDA_IN_DATA(); //这句改为这样好点 --> if(SDA_IN_DATA()) data |= 0x01; //收到高电平 
data = (data << 1) | temp; //这句就改为 --> data <<= 1; //否则收到低电平 

把上述你的指出的修改,修改为我最原始的代码,读写数据正常。

感谢你的多次回复,谢谢!!
你也看看你的代码是不是存在瑕疵。
八度空间
5楼-- · 2019-07-21 18:55
 精彩回答 2  元偷偷看……
八度空间
6楼-- · 2019-07-21 22:12
回复【11楼】magni:
---------------------------------
我的写字节函数
u8 IIC_Write_Byte(u8 dat)
{
u8 i;
u8 iic_ack=0; //iic应答标志

IIC_SDA_OUT(); //设置成输出

for(i = 0;i < 8;i++)
{
if(dat & 0x80) IIC_SDA = 1; //判断发送位,先发送高位
else IIC_SDA = 0;

IIC_Delay();
IIC_SCL = 1; //为SCL下降做准备
IIC_Delay();
IIC_SCL = 0; //突变,将数据位发送过去
dat<<=1; //数据左移一位
} //字节发送完成,开始接收应答信号

IIC_SDA = 1; //释放数据线

IIC_SDA_IN(); //设置成输入

IIC_Delay();
IIC_SCL = 1; //为SCL下降做准备
IIC_Delay();
iic_ack |= IN_SDA; //读入应答位
IIC_SCL = 0;
return iic_ack; //返回应答信号
}

我的读取字节函数

u8 IIC_Read_Byte(void)
{
u8 i;
u8 x=0;

IIC_SDA = 1; //首先置数据线为高电平

IIC_SDA_IN(); //设置成输入

for(i = 0;i < 8;i++)
{
x <<= 1; //读入数据,高位在前

IIC_Delay();
IIC_SCL = 1; //突变
IIC_Delay();

if(IN_SDA) x |= 0x01; //收到高电平

IIC_SCL = 0;
IIC_Delay();
} //数据接收完成
IIC_SCL = 0;

return x; //返回读取到的数据
}

一周热门 更多>