找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1298|回复: 12
收起左侧

请教大神们 :STM32模拟IIC通讯

[复制链接]
ID:461428 发表于 2020-11-16 16:26 | 显示全部楼层 |阅读模式
我写的H和C文件都复制在下面 请教下  程序不能正常通讯  是不是哪儿错了?谢谢

#ifndef __iic_H
#define __iic_H

#include "sys.h"
#include "delay.h"
//IO方向设置
#define SDA_IN() {GPIOB->CRH&=0XFFFFFF0F;GPIOB->CRH|=8<<4;}//此处应该=0XFFFFFF0F这才是管脚9
#define SDA_OUT() {GPIOB->CRH&=0XFFFFFF0F;GPIOB->CRH|=3<<4;}//此处应该=0XFFFFFF0F
//IO操作函数         
#define IIC_SCL    PBout(8) //SCL
#define IIC_SDA    PBout(9) //SDA         
#define READ_SDA   PBin(9)
//extern IIC_Init();
//IIC所有操作函数
                         
void IIC_Start(void);                                //发送IIC开始信号
void IIC_Stop(void);                                  //发送IIC停止信号
void IIC_Send_Byte(u8 txd);                        //IIC发送一个字节
u8 IIC_Wait_Ack(void);                                 //IIC等待ACK信号
void IIC_Ack(void);                                        //IIC发送ACK信号
void IIC_NAck(void);                                //IIC不发送ACK信号
void IIC_Write_One_Byte(u8 daddr,u8 addr,u8 data);
u8 IIC_Read_One_Byte(u8 daddr,u8 addr);         
void IIC_Init(void);
u8 IIC_Read_Byte(void);               //IIC读取一个字节
#endif
以上为我的H文件下面是C 文件
#include "iic.h"

//初始化IIC  |RCC_APB2Periph_AFIO   GPIO_Mode_Out_PP  GPIO_Mode_AF_OD GPIO_Mode_AF_OD
void IIC_Init(void)//|RCC_APB2Periph_AFIO,
{                       
        GPIO_InitTypeDef  GPIO_InitStructure;          
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE);  //
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8| GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_Out_PP; //推挽输出  GPIO_Mode_Out_OD
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//50MHz
    GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化
        IIC_SCL=1;
        IIC_SDA=1;
}
//产生IIC起始信号
void IIC_Start(void)
{
        SDA_OUT();  
        IIC_SDA=1;       
    delay_us(5);   
        IIC_SCL=1;
        delay_us(5);
        IIC_SDA=0;
        delay_us(5);
        IIC_SCL=0;
}          
//产生IIC停止信号
void IIC_Stop(void)
{
    SDA_OUT();  
        IIC_SDA=0;
        delay_us(5);
        IIC_SCL=1;
    delay_us(5);
        IIC_SDA=1;
        delay_us(5);                                                                  
}
//等待应答信号到来
//返回值:1,接收应答失败
//       0,接收应答成功
u8 IIC_Wait_Ack(void)
{
        u8 ASK=0;  
   SDA_IN();
        IIC_SCL=1;
        while(READ_SDA)
        {
                ASK++;delay_us(100);
                if(ASK>250)
                {
                        IIC_Stop();
            
                        return 1;
                }
        }
        IIC_SCL=0;//时钟输出0           
        return 0;  
}
//产生ACK应答
void IIC_Ack(void)
{
        u8 i;
  
  IIC_SCL=0;                  
        while (IIC_SDA==1&&i<250)i++;
   delay_us(5);               
IIC_SCL=0;                  
   delay_us(5);            
}

void IIC_Send_Byte(u8 txd)
{                        
    u8 t;  
    SDA_OUT()  
    IIC_SCL=0;
    for(t=0;t<8;t++)
    {              
       if(txd&0x80)IIC_SDA=1;
        else IIC_SDA=0;
                 
                delay_us(5);   
                IIC_SCL=1;
                delay_us(5);
                IIC_SCL=0;                       
         txd<<=1;
                delay_us(5);
    }         
}

//读1个字节   
u8 IIC_Read_Byte()
{
        unsigned char i,receive=0;
   SDA_IN();
     IIC_SDA=1;
    delay_us(3);
    for(i=0;i<8;i++ )
        {
        IIC_SCL=1;
        delay_us(5);               
        receive<<=1;
       receive|=READ_SDA;
        delay_us(5);      
        IIC_SCL=0;
         delay_us(5);
    }                                         
   
    return receive;
}
回复

使用道具 举报

ID:461428 发表于 2020-11-16 16:33 | 显示全部楼层
使用时检查应答信号。然后通过串口打印出来错误结果都是开始信号失败
回复

使用道具 举报

ID:461428 发表于 2020-11-16 16:33 | 显示全部楼层
串口打印的错误如下开始信号发送失败! 器件地址82发送成功! 寄存器地址20发送成功! 开始信号发送失败! 读命令83发送成功! 读数据失败!
回复

使用道具 举报

ID:568565 发表于 2020-11-16 16:34 | 显示全部楼层
大致看了一下好像没什么问题,最好用逻辑分析仪查一查
回复

使用道具 举报

ID:461428 发表于 2020-11-16 16:41 | 显示全部楼层
chenyinhu 发表于 2020-11-16 16:34
大致看了一下好像没什么问题,最好用逻辑分析仪查一查

逻辑分析仪这东西还真没有。我在考虑是不是我硬件接法问题?AL53L1激光测距芯片。XSHUT.GPIO_1. SDA.SCL都接了4.7K上拉电阻电源3.3.
回复

使用道具 举报

ID:827243 发表于 2020-11-16 16:41 | 显示全部楼层
  1. #include "i2c2.h"
  2. #define I2C2_EN
  3. #define I2C2_DIS

  4. void LL_IWDG_ReloadCounter(IWDG_TypeDef *IWDGx);
  5. void I2C_delay(void)
  6. {
  7.         u8 t = 50;
  8.         while(t--);
  9.         LL_IWDG_ReloadCounter(IWDG);
  10.         return;
  11. }
  12. int I2C_Start(void)
  13. {
  14.         I2C_SDA_OUT();
  15.        
  16.         SCL_L;
  17.         SDA_H;
  18.         SCL_H;
  19.         I2C_delay();
  20.         if(!SDAO_read)
  21.         {
  22.                 return DISABLE;
  23.         }
  24.         SDA_L;
  25.         I2C_delay();
  26.         if(SDAO_read)
  27.         {
  28.                 return DISABLE;
  29.         }
  30.         SCL_L;
  31.         SDA_H;
  32.         return ENABLE;
  33. }
  34. void I2C_Stop(void)
  35. {
  36.         I2C_SDA_OUT();       
  37.         SCL_L;
  38.         SDA_L;       
  39.         SCL_H;
  40.         I2C_delay();
  41.         SDA_H;
  42.         I2C_delay();
  43.         SCL_L;
  44. }

  45. void I2C_Ack()
  46. {
  47.         SCL_L;
  48.         I2C_SDA_OUT();
  49.        
  50.         SDA_L;
  51.         I2C_delay();
  52.         SCL_H;
  53.         I2C_delay();
  54.         SCL_L;
  55.         SDA_H;
  56. }

  57. void I2C_NoAck()
  58. {
  59.        
  60.         SCL_L;
  61.         I2C_SDA_OUT();
  62.        
  63.         I2C_delay();
  64.         SDA_H;
  65.         I2C_delay();
  66.         SCL_H;
  67.         I2C_delay();
  68.         SCL_L;
  69. }
  70. uint8_t I2C_GetAck(void)
  71. {
  72.   uint8_t time = 0;
  73.         I2C_SDA_IN();
  74.         SDA_H;
  75.         I2C_delay();
  76.         SCL_H;
  77.         I2C_delay();
  78.         while(SDA_read)
  79.         {
  80.                 time++;
  81.                 if(time > 250)
  82.                 {                       
  83.                         SCL_L;
  84.                         return DISABLE;
  85.                 }
  86.         }
  87.         SCL_L;
  88.         return ENABLE;
  89. }
  90. void I2C_SendByte(uint8_t Data)
  91. {
  92.   uint8_t cnt;
  93.   I2C_SDA_OUT();       
  94.   for(cnt=0; cnt<8; cnt++)
  95.   {
  96.     SCL_L;                              
  97.     I2C_delay();

  98.     if(Data & 0x80)
  99. //    if(Data & 0x01)
  100.     {
  101.       SDA_H;                        
  102.     }
  103.     else
  104.     {
  105.       SDA_L;                        
  106.     }
  107.     Data <<= 1;
  108. //    Data >>= 1;
  109.     SCL_H;                              
  110.     I2C_delay();
  111.   }
  112.   SCL_L;                                   
  113.   I2C_delay();
  114. }


  115. uint8_t I2C_ReadByte(uint8_t ack)
  116. {
  117.   uint8_t cnt;
  118.   uint16_t data;
  119.   I2C_SDA_IN();       
  120.        
  121.   for(cnt=0; cnt<8; cnt++)
  122.   {
  123.     SCL_L;                                
  124.     I2C_delay();
  125.                
  126.     SCL_H;                             
  127.     data <<= 1;
  128.     if(SDA_read)
  129.     {
  130.       data |= 0x01;                              
  131.     }
  132.     I2C_delay();
  133.   }
  134.   if(ack == 1)
  135.   {
  136.      I2C_NoAck();
  137.   }
  138.   else
  139.   {
  140.      I2C_Ack();
  141.   }
  142.   return data;                                 
  143. }
  144. void I2C_GPIO_Configuration(void)
  145. {
  146.   LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

  147.   /* GPIO Ports Clock Enable */
  148.   LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOB);

  149.   GPIO_InitStruct.Pin = LL_GPIO_PIN_6|LL_GPIO_PIN_7;
  150.   GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
  151.   GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
  152.   GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  153.   LL_GPIO_Init(GPIOB, &GPIO_InitStruct);


  154. }


  155. void I2C_SDA_IN()
  156. {
  157.   LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

  158.   GPIO_InitStruct.Pin = I2C_Pin_SDA;
  159.   GPIO_InitStruct.Mode = LL_GPIO_MODE_INPUT;
  160.   LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  161. }

  162. void I2C_SDA_OUT()
  163. {
  164.   LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

  165.   GPIO_InitStruct.Pin = I2C_Pin_SDA;
  166.   GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
  167.   GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
  168.   GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  169.   LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  170. }
  171. void I2C_Initializes(void)
  172. {
  173.         I2C_GPIO_Configuration();
  174.   SCL_H;
  175.         SDA_H;
  176. }
  177. int EEPROM_WriteByte(uint16_t Addr, uint8_t Data)
  178. {
  179.         u16 i;
  180.        
  181.         I2C2_EN;
  182.         I2C_Start();
  183.         I2C_SendByte(EEPROM_DEV_ADDR | EEPROM_WR);
  184.   if(!I2C_GetAck())
  185.   {
  186.         I2C_Stop();
  187.         return DISABLE;
  188.   }
  189.   #if (8 == EEPROM_WORD_ADDR_SIZE)
  190.   I2C_SendByte((uint8_t)(Addr&0x00FF));   
  191.   #else
  192.   I2C_SendByte((uint8_t)(Addr>>8));
  193.   I2C_GetAck();
  194.   I2C_SendByte((uint8_t)(Addr&0x00FF));
  195.   #endif
  196.   I2C_GetAck();
  197.   I2C_SendByte(Data);
  198.   I2C_GetAck();
  199.         I2C_delay();
  200.   I2C_Stop();
  201.         I2C_delay();
  202.         I2C2_DIS;
  203.         for (i=0;i<500;i++) I2C_delay();
  204.         return 1;
  205. }

  206. #define OLED_ADDRESS 0x78

  207. int OLED_WriteByte(uint8_t Addr, uint8_t Data)
  208. {
  209.         u16 i;
  210.        
  211.         I2C2_EN;
  212.         I2C_Start();
  213.         I2C_SendByte(0x78);
  214.   if(!I2C_GetAck())
  215.   {
  216.         I2C_Stop();
  217.         return DISABLE;
  218.   }
  219.   I2C_SendByte(Addr);   
  220.   I2C_GetAck();
  221.   I2C_SendByte(Data);
  222.   I2C_GetAck();
  223.         I2C_delay();
  224.   I2C_Stop();
  225.         I2C_delay();
  226.         return 1;
  227. }

  228. int EEPROM_ReadByte(uint16_t Addr, uint8_t *Data)
  229. {
  230.         u16 i;
  231.        
  232.         I2C2_EN;
  233.   I2C_Start();
  234.         I2C_SendByte(EEPROM_DEV_ADDR | EEPROM_WR);
  235.   if(!I2C_GetAck())
  236.   {
  237.         I2C_Stop();
  238.         return DISABLE;
  239.   }
  240.   #if (8 == EEPROM_WORD_ADDR_SIZE)
  241.   I2C_SendByte((uint8_t)(Addr&0x00FF));
  242.   #else
  243.   I2C_SendByte((uint8_t)(Addr>>8));   
  244.   I2C_GetAck();
  245.         I2C_SendByte((uint8_t)(Addr&0x00FF));
  246.   #endif
  247.   I2C_GetAck();
  248.   I2C_Start();
  249.         I2C_SendByte(EEPROM_DEV_ADDR | EEPROM_RD);
  250.        
  251.         if(!I2C_GetAck())
  252.         {
  253.         I2C_Stop();
  254.         return DISABLE;
  255.   }
  256.   *Data = I2C_ReadByte(0);
  257.   I2C_GetAck();
  258.         I2C_delay();
  259.         I2C_Stop();
  260.         I2C_delay();
  261.         I2C2_DIS;
  262.         for (i=0;i<500;i++) I2C_delay();
  263.         return 1;
  264. }
  265. u8 Who_Am_I(void)
  266. {
  267.         u8 who;
  268.         EEPROM_ReadByte(0x20, &who);
  269.         return who;
  270. }
  271. u8 Sanzhou_Start()
  272. {
  273.         u8 id;
  274.         id = Who_Am_I();
  275.         if(id)
  276.         {
  277.                 EEPROM_WriteByte(0x20, 0xE7);
  278.                 return ENABLE;
  279.         }
  280.         else
  281.                 return DISABLE;
  282. }
复制代码

给你段我调试通过的代码吧。
回复

使用道具 举报

ID:461428 发表于 2020-11-16 17:46 | 显示全部楼层
daemondong 发表于 2020-11-16 16:41
给你段我调试通过的代码吧。

谢谢你哈  我来试试  
回复

使用道具 举报

ID:461428 发表于 2020-11-16 17:52 | 显示全部楼层
daemondong 发表于 2020-11-16 16:41
给你段我调试通过的代码吧。

H文件一并给我吧 不然修改幅度太大了  谢谢哦
回复

使用道具 举报

ID:342954 发表于 2020-11-16 18:21 | 显示全部楼层
把延时调慢试试
回复

使用道具 举报

ID:461428 发表于 2020-11-16 19:36 | 显示全部楼层

调过  调大调小  都没作用  都是开始信号发出后  从设备没回应。谢谢
回复

使用道具 举报

ID:827243 发表于 2020-11-17 08:41 | 显示全部楼层

  1. #ifndef __i2c2_H
  2. #define __i2c2_H

  3. #include "main.h"
  4. #include "GloablVar.h"

  5. #define ANO_GPIO_I2C    GPIOB
  6. #define I2C_Pin_SCL     LL_GPIO_PIN_6
  7. #define I2C_Pin_SDA     LL_GPIO_PIN_7
  8. #define ANO_RCC_I2C     LL_RCC_APB2Periph_GPIOB
  9. /*********************************************/

  10. #define SCL_H         LL_GPIO_SetOutputPin(GPIOB, I2C_Pin_SCL)
  11. #define SCL_L         LL_GPIO_ResetOutputPin(GPIOB, I2C_Pin_SCL)
  12. //#define SCL_H         GPIO_SetBits(GPIOB,GPIO_Pin_10)
  13. //#define SCL_L         GPIO_ResetBits(GPIOB,GPIO_Pin_10)
  14. #define SDA_H         LL_GPIO_SetOutputPin(GPIOB, I2C_Pin_SDA)
  15. #define SDA_L         LL_GPIO_ResetOutputPin(GPIOB, I2C_Pin_SDA)
  16. #define SCL_read      LL_GPIO_IsInputPinSet(GPIOB, I2C_Pin_SCL)
  17. #define SDA_read      LL_GPIO_IsInputPinSet(GPIOB, I2C_Pin_SDA)
  18. #define SDAO_read      LL_GPIO_IsOutputPinSet(GPIOB, I2C_Pin_SDA)

  19. #define EEPROM_DEV_ADDR           0xA0           //??(????)
  20. #define EEPROM_WR                 0x00                     //?
  21. #define EEPROM_RD                 0x01                     //?
  22. #define EEPROM_WORD_ADDR_SIZE     16
  23. extern u8 databuff[3];
  24. extern u8 x,y,z;
  25. int I2C_Start(void);
  26. void I2C_Stop(void);
  27. void I2C_Ack(void);
  28. void I2C_NoAck(void);
  29. void I2C_SDA_OUT(void);
  30. void I2C_SDA_IN(void);
  31. uint8_t I2C_GetAck(void);
  32. void I2C_SendByte(uint8_t Data);
  33. uint8_t I2C_ReadByte(uint8_t ack);
  34. void I2C_delay(void);
  35. int EEPROM_ReadByte(uint16_t Addr, uint8_t *Data);
  36. int EEPROM_WriteByte(uint16_t Addr, uint8_t Data);
  37. void I2C_Initializes(void);
  38. u8 Sanzhou_Start(void);
  39. u8 Who_Am_I(void);
  40. int Read_XYZ(void);
  41. #endif /*__ i2c_H */

  42. /**
  43.   * @}
  44.   */

  45. /**
  46.   * @}
  47.   */

  48. /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
复制代码

I2C.h 如下。
回复

使用道具 举报

ID:461428 发表于 2020-11-17 13:47 | 显示全部楼层

灰常感谢 我先来用用 IIC程序卡了我3个月了  业余爱好者
回复

使用道具 举报

ID:461428 发表于 2020-11-17 14:36 | 显示全部楼层

H文件没有涵盖所有使用参数的定义。编译出错很多 提示没定义的字符串。还是感谢您的热心  谢谢
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表