找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2002|回复: 0
打印 上一主题 下一主题
收起左侧

改进型STM32模拟IIC 源程序

[复制链接]
跳转到指定楼层
楼主
ID:269804 发表于 2019-11-2 20:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
最近在研究MPU6050,但是MPU6050的底层驱动又不想自己写,那怎么办呢我就想到了去移植正点原子的代码,但是打开代码一看需要修改寄存器值 那意味着要去翻数据是手册,我这个人本身比较懒不想去翻,也为了以后不翻,于是乎我想到了自己动手写模拟IIC的代码。写的过程中我就发现一个问题为什么每次都要管脚切换方向非常麻烦(本人非常烦这一点),于是乎我就在想有没有办法不切换方向去读数据。最后我终于在野火的树上找到了这样一句话“STM32的管脚在输出模式下也可以读到数据”,起初我对这句话半信半疑于是我自己做了一波实验,把管脚配置成输出模式(推挽和开漏都配置了)结果真的能读到数据不过要使用函数GPIO_ReadInputDataBit去读IDR寄存器的值。用位带操作就是不行。然后抱着这个结果我就开始了写IIC。在这里对IIC协议不再介绍,毕竟网上大佬挺多的随便改都能找到协议的说明。我的代码最大的好处就是容易移植容易修改废话不多说了开始附上代码。

单片机源程序如下:
  1. #include "bsp_i2c_ee.h"

  2. /*适用于STM32F103系列*/
  3. void IIC_Init(void)   //初始化IIC总线所用到的端口
  4. {
  5.                 GPIO_InitTypeDef IICBUS;
  6.           IICBUS.GPIO_Mode = GPIO_Mode_Out_OD;
  7.                 IICBUS.GPIO_Speed = GPIO_Speed_50MHz;
  8.                 IICBUS.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;   //修改
  9.                 GPIO_Init(GPIOA,&IICBUS);                  //修改
  10.                 GPIO_SetBits(GPIOA,GPIO_Pin_0|GPIO_Pin_1); // 修改 //拉高总线(释放总线)不进行操作
  11.                         
  12. }

  13. static void  IIC_Delay(void) //IIC延时函数对总线速度进行控制
  14. {
  15.    u8 i = 0;
  16.          /* 
  17.                  下面的时间是通过逻辑分析仪测试得到的。
  18.     工作条件:CPU主频72MHz ,MDK编译环境,1级优化
  19.                 循环次数为10时,SCL频率 = 205KHz
  20.                 循环次数为7时,SCL频率 = 347KHz, SCL高电平时间1.5us,SCL低电平时间2.87us
  21.                  循环次数为5时,SCL频率 = 421KHz, SCL高电平时间1.25us,SCL低电平时间2.375us
  22.         */
  23.         for (i = 0; i < 7; i++);        
  24. }


  25. //  IIC起始信号
  26. void IIC_Start(void)   
  27. {
  28.                 SDA_SETB;
  29.                 SCL_SETB;
  30.                 IIC_Delay();
  31.                 SDA_CLR;
  32.                 IIC_Delay();
  33.                 SCL_CLR;
  34. }

  35. // IIC停止信号
  36. void IIC_Stop(void)
  37. {
  38.                 SCL_CLR;
  39.                 SDA_CLR;
  40.                 SCL_SETB;
  41.           IIC_Delay();
  42.                 SDA_SETB;
  43.                 IIC_Delay();
  44. }

  45. //IIC主机产生应答信号
  46. void IIC_Ack(void)
  47. {
  48.                 SCL_CLR;
  49.                 SDA_CLR;
  50.                 IIC_Delay();
  51.                 SCL_SETB;
  52.                 IIC_Delay();
  53.                 SCL_CLR;
  54. }

  55. //IIC主机不应答
  56. void IIC_Nack(void)
  57. {
  58.                 SCL_CLR;
  59.                 SDA_SETB;
  60.                 IIC_Delay();
  61.                 SCL_SETB;
  62.                 IIC_Delay();
  63.                 SCL_CLR;
  64.                
  65. }



  66. //IIC主机等待从机应答

  67. u8 IIC_WaitAck(void)
  68. {
  69.           u8 timeout = 0;
  70.                 SDA_SETB;
  71.                 IIC_Delay();
  72.                 SCL_SETB;
  73.                 IIC_Delay();
  74.           while(SDA_Read)//读取
  75.                 {        
  76.                                 if(++timeout>250)
  77.                                 {
  78.                                                 IIC_Stop();
  79.                                                 return 1; //超时没有应答
  80.                                 }
  81.                 }
  82.                 SCL_CLR;
  83.                 return 0; //应答了        
  84. }


  85. //IIC总线发送一组数据
  86. void IIC_SendByte(u8 TXData)
  87. {
  88.                 u8 i = 0;
  89.                 SCL_CLR;
  90.                 for(i = 0;i<8;i++)
  91.                 {
  92.                                 if(TXData&0x80)
  93.                                 {
  94.                                                 SDA_SETB;
  95.                                 }
  96.                                 else
  97.                                 {
  98.                                                 SDA_CLR;
  99.                                 }
  100.                                 IIC_Delay();
  101.                                 SCL_SETB;
  102.                                 IIC_Delay();
  103.                                 SCL_CLR;
  104.                                 TXData<<=1;
  105.                 }
  106. }

  107. //读取一byte数据
  108. //ack = 1;应答
  109. //ack = 0;不应答
  110. u8 IIC_ReadByte(u8 ack)
  111. {
  112.                  u8 Receive = 0;
  113.                  u8 i = 0;
  114.                  for(i=0;i<8;i++)
  115.                  {
  116.                          SCL_CLR;
  117.                          IIC_Delay();
  118.                          SCL_SETB;
  119.                          Receive<<=1; //先左移动一位空位置出来
  120.                          if(SDA_Read)
  121.                          {
  122.                                         Receive ++;
  123.                          }
  124.                          IIC_Delay();
  125.                  }
  126.                  if(ack)
  127.                  {
  128.                                 IIC_Ack(); //产生应答信号
  129.                  }
  130.                  else
  131.                  {
  132.                                 IIC_Nack();//不产生应答信号
  133.                  }
  134.                  return Receive;
  135. }


  136. //返回0检测到了设备
  137. //返回1没有检测到设备
  138. //参数是你所要检测的设备的地址
  139. u8 IIC_CheckDevice(u8 __Address)//检测外部是否挂载了从机
  140. {
  141.         u8 ucAck = 0;
  142.         IIC_Init();
  143.         IIC_Start();
  144.         IIC_SendByte(__Address|IIC_Wr);
  145.         ucAck = IIC_WaitAck();
  146.         IIC_Stop();
  147.         return ucAck;
  148. }

复制代码
全部资料51hei下载地址:
i2c.zip (1.82 KB, 下载次数: 31)

评分

参与人数 1黑币 +100 收起 理由
admin + 100 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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