你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

学习机器风格的单片机程序(4)

[复制链接]
与龙共舞 发布时间:2018-5-18 11:31
本帖最后由 与龙共舞 于 2018-6-11 09:17 编辑

这是最后一篇。自己昨天完成的一个工程,终于自己动手写出了人人喊打的代码

+++++++++++++项目介绍++++++++++++++++
逛论坛时间不长,新人,偶然看到@游名 发帖子免费申请按键板,我就参加了。
其实我公司也有做门禁的,我也是公司新人,业务不懂,就先玩玩吧。
货到付款,相当于15块钱买了一个小板子。
提供的资料很全,有历程代码,有规格书。
1111.jpg
+++++++++++框架介绍++++++++++++++++
工作逻辑:按键板一共6个脚连接到STM32主控板
1上电(不管)
2接地(不管)
3复位(就是接到STM32的一个GPIO,先拉高在拉低在拉高就可以让这个按键板复位一次)
4中断 (也是接到STM32的一个GPIO,当有按键被按的时候这个电平会突然拉高,也就触发了中断线。然后你去就IIC总线读数据)
5(IIC SDA)
6 (IIC SCL)
所以主要知识点是:A中断线(类似于很多教程里面的按键触发LED灯亮起)B IIC通讯(类似有ATC02存储的教程)
++++++++开始吧+++++++++++
2222.png
3333.png
后面的配置都没有修改。(用了一个TIM定时器来做延时)

A.png
B.png
C.png

D.png

E.png
基于cubemx+硬件IIC 几分钟就跑通了。
很快问题也就来了。(反馈给HTK公司技术的视频)
https://pan.baidu.com/s/10pr82ORcf4lanSPKwMdPHw
数据是00-32-32-32,虽然可以用,但有点膈应。
于是打算放弃硬件IIC,自己也来模拟IIC吧。
所以回到标题:机器风格的单片机程序
  1. #include "HALI2C.h"

  2. _STM32I2CHandleType TemIIC;
  3. STM32I2CHandleType  pSTM32I2C=&TemIIC;

  4. /*初始化 时钟 GPIO 两线都高*/
  5. void I2C_init(void)
  6. {        
  7.         GPIO_InitTypeDef GPIO_InitStruct;
  8.         __HAL_RCC_GPIOD_CLK_ENABLE();
  9.         __HAL_RCC_GPIOA_CLK_ENABLE();
  10.         __HAL_RCC_GPIOB_CLK_ENABLE();
  11.         GPIO_InitStruct.Pin=pSTM32I2C->SCL_PIN|pSTM32I2C->SDA_PIN;
  12.         GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  13.         GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;/*推荐复用输出*/
  14.         HAL_GPIO_Init(pSTM32I2C->IICGPIO, &GPIO_InitStruct);

  15.         pSTM32I2C->Set_SDA();
  16.         pSTM32I2C->Set_SCL();
  17. }
  18. /*设置SDA为输出模式*/
  19. void I2C_SDA_OUT(void)
  20. {
  21.   GPIO_InitTypeDef GPIO_InitStruct;        
  22.         
  23.         GPIO_InitStruct.Pin=pSTM32I2C->SCL_PIN|pSTM32I2C->SDA_PIN;
  24.         GPIO_InitStruct.Speed=GPIO_SPEED_FREQ_HIGH;
  25.         GPIO_InitStruct.Mode=GPIO_MODE_OUTPUT_PP;
  26.         HAL_GPIO_Init(pSTM32I2C->IICGPIO, &GPIO_InitStruct);
  27. }
  28. /*设置SDA为输入模式*/
  29. void I2C_SDA_IN(void)
  30. {
  31.         GPIO_InitTypeDef GPIO_InitStruct;        
  32.         
  33.         GPIO_InitStruct.Pin=pSTM32I2C->SDA_PIN;
  34.         GPIO_InitStruct.Mode=GPIO_MODE_INPUT;
  35.         HAL_GPIO_Init(pSTM32I2C->IICGPIO, &GPIO_InitStruct);
  36. }

  37. /*产生起始信号*/
  38. void I2C_Start(void)
  39. {
  40.         pSTM32I2C->Set_SDA_Output_Mode();
  41.         pSTM32I2C->Set_SDA();
  42.         pSTM32I2C->Set_SCL();
  43.         pSTM32I2C->Delayus(5);
  44.         pSTM32I2C->Reset_SDA();
  45.         pSTM32I2C->Delayus(5);
  46.         pSTM32I2C->Reset_SCL();
  47.         pSTM32I2C->Delayus(5);
  48. }

  49. /*产生停止信号*/
  50. void I2C_Stop(void)
  51. {
  52.    pSTM32I2C->Set_SDA_Output_Mode();
  53.    pSTM32I2C->Reset_SCL();
  54.    pSTM32I2C->Reset_SDA();
  55.    pSTM32I2C->Set_SCL();
  56.    pSTM32I2C->Delayus(6);
  57.    pSTM32I2C->Set_SDA();
  58.    pSTM32I2C->Delayus(6);
  59. }

  60. //主机产生应答信号ACK
  61. void I2C_Ack(void)
  62. {
  63.    pSTM32I2C->Reset_SCL();
  64.          pSTM32I2C->Delayus(2);
  65.    pSTM32I2C->Set_SDA_Output_Mode();
  66.    pSTM32I2C->Reset_SDA();
  67.    pSTM32I2C->Delayus(5);
  68.    pSTM32I2C->Set_SCL();
  69.    pSTM32I2C->Delayus(5);
  70.    pSTM32I2C->Reset_SCL();
  71. }

  72. //主机不产生应答信号NACK
  73. void I2C_NAck(void)
  74. {
  75.          pSTM32I2C->Reset_SCL();
  76.          pSTM32I2C->Delayus(2);
  77.    pSTM32I2C->Set_SDA_Output_Mode();
  78.    pSTM32I2C->Set_SDA();
  79.    pSTM32I2C->Delayus(5);
  80.    pSTM32I2C->Set_SCL();
  81.    pSTM32I2C->Delayus(5);
  82.    pSTM32I2C->Reset_SCL();
  83.          pSTM32I2C->Delayus(2);
  84. }
  85. //等待从机应答信号
  86. //返回值:1 接收应答失败
  87. //                    0 接收应答成功
  88. unsigned char I2C_Wait_Ack(void)
  89. {
  90.         unsigned char tempTime=0;

  91.         pSTM32I2C->Set_SDA_Input_Mode();

  92.         pSTM32I2C->Set_SDA();
  93.         pSTM32I2C->Delayus(5);
  94.         pSTM32I2C->Set_SCL();
  95.         pSTM32I2C->Delayus(2);


  96.         while(pSTM32I2C->Get_SDA())
  97.         {
  98.                 tempTime++;
  99.                 if(tempTime>50)
  100.                 {
  101.                         pSTM32I2C->I2C_stop();
  102.                         return 0;
  103.                 }         
  104.         }

  105.         pSTM32I2C->Reset_SCL();
  106.         pSTM32I2C->Delayus(5);
  107.         return 1;
  108. }
  109. //I2C 发送一个字节
  110. void I2C_Send_Byte(unsigned char txd)
  111. {
  112.         unsigned char i=0;

  113.         pSTM32I2C->Set_SDA_Output_Mode();
  114.         pSTM32I2C->Reset_SCL();//拉低时钟开始数据传输

  115.         for(i=0;i<8;i++)
  116.         {
  117.                 if((txd<<i)&0x80)
  118.                         pSTM32I2C->Set_SDA();
  119.                 else
  120.                         pSTM32I2C->Reset_SDA();
  121.                
  122.           pSTM32I2C->Delayus(2);
  123.                 pSTM32I2C->Set_SCL();
  124.                 pSTM32I2C->Delayus(5); //发送数据
  125.                 pSTM32I2C->Reset_SCL();
  126.                 pSTM32I2C->Delayus(2);
  127.         }
  128. }

  129. //I2C 读取一个字节

  130. unsigned char I2C_Read_Byte(unsigned char ack)
  131. {
  132.    unsigned char i=0,receive=0;

  133.    pSTM32I2C->Set_SDA_Input_Mode();
  134.    for(i=0;i<8;i++)
  135.    {
  136.            pSTM32I2C->Reset_SCL();
  137.                 pSTM32I2C->Delayus(5);
  138.                 pSTM32I2C->Set_SCL();
  139.                 receive<<=1;
  140.                 if(pSTM32I2C->Get_SDA())
  141.                    receive++;
  142.                 pSTM32I2C->Delayus(5);        
  143.    }

  144.            if(ack==0)
  145.                    pSTM32I2C->I2C_withnoAck();
  146.           else
  147.                   pSTM32I2C->I2C_withAck();

  148.         return receive;
  149. }

  150. void set_SDA(void)
  151. {
  152.         HAL_GPIO_WritePin(pSTM32I2C->IICGPIO,pSTM32I2C->SDA_PIN,GPIO_PIN_SET);
  153. }
  154. void set_SCL(void)
  155. {
  156.         HAL_GPIO_WritePin(pSTM32I2C->IICGPIO,pSTM32I2C->SCL_PIN,GPIO_PIN_SET);
  157. }
  158. void reset_SDA(void)
  159. {
  160.         HAL_GPIO_WritePin(pSTM32I2C->IICGPIO,pSTM32I2C->SDA_PIN,GPIO_PIN_RESET);
  161. }
  162. void reset_SCL(void)
  163. {
  164.         HAL_GPIO_WritePin(pSTM32I2C->IICGPIO,pSTM32I2C->SCL_PIN,GPIO_PIN_RESET);
  165. }
  166. unsigned char read_SDAPIN(void)
  167. {
  168.   return HAL_GPIO_ReadPin(pSTM32I2C->IICGPIO,pSTM32I2C->SDA_PIN);
  169. }
  170. ///////////////////设备驱动//////////////////////

  171. void STM32IICInit(void)
  172. {
  173.         _STM32I2CHandleType temIIC=
  174.         {
  175.         .IICGPIO=GPIOB,
  176.         .SCL_PIN=GPIO_PIN_6,
  177.         .SDA_PIN=GPIO_PIN_7,
  178.         .I2C_Init=I2C_init,
  179.         .Set_SDA=set_SDA,
  180.         .Set_SCL=set_SCL,
  181.         .Reset_SDA=reset_SDA,
  182.         .Reset_SCL=reset_SCL,
  183.         .Get_SDA=read_SDAPIN,
  184.         .Delayus=TIM3_Delay,
  185.         .Set_SDA_Input_Mode=I2C_SDA_IN,
  186.         .Set_SDA_Output_Mode=I2C_SDA_OUT,
  187.         .I2C_start=I2C_Start,
  188.         .I2C_stop=I2C_Stop,
  189.         .I2C_withAck=I2C_Ack,
  190.         .I2C_withnoAck=I2C_NAck,
  191.         .I2C_Wait_Ack_Check=I2C_Wait_Ack,
  192.         .I2C_read_byte=I2C_Read_Byte,
  193.         .I2C_send_byte=I2C_Send_Byte,
  194.         };
  195. TemIIC=temIIC;/*做了一个临时变量 然后用=号做了赋值*/
  196. pSTM32I2C->I2C_Init();
  197. }
  198. +++++++++++++++++++噢这不好 可以直接赋值的int a=9这样直接全局变量赋值+++++++++++++

  199. char __HTK_I2C_Read_optimal_touch_keyval(unsigned char  *pKeyVal)
  200. {
  201. /*第一次发送器件物理地址+写命令*/
  202.         pSTM32I2C->I2C_start();
  203.         pSTM32I2C->Delayus(5);
  204.         pSTM32I2C->I2C_send_byte((0X24<<1)|0) ;
  205.   pSTM32I2C->I2C_Wait_Ack_Check();//等待从机收到消息,电平拉低标识

  206.         
  207. /*第二次发送器件内部地址*/        
  208.         pSTM32I2C->Delayus(5);
  209.         pSTM32I2C->I2C_send_byte(0X80);
  210.   pSTM32I2C->I2C_Wait_Ack_Check();//等待从机收到消息,电平拉低标识        

  211.         
  212.   pSTM32I2C->Delayus(5);

  213. /*第三次发送器件物理地址+读命令*/               
  214.         pSTM32I2C->I2C_start();
  215.         pSTM32I2C->Delayus(5);
  216.         pSTM32I2C->I2C_send_byte((0X24<<1)|1) ;               
  217.   pSTM32I2C->I2C_Wait_Ack_Check();//等待从机收到消息,电平拉低标识        


  218.         pSTM32I2C->Delayus(100);
  219. /*读取反馈数据 因为只读一个字节 所以不需要ack反馈信号*/        
  220.         *pKeyVal = pSTM32I2C->I2C_read_byte(0);
  221.         
  222.         pSTM32I2C->Delayus(5);
  223.         pSTM32I2C->I2C_stop();        
  224.         return 1;
  225. }



  226. char __HTK_I2C_Read_keystatus(unsigned char  *pKeyVal)
  227. {
  228.         char i=0;
  229. /*第一次发送器件物理地址+写命令*/
  230.         pSTM32I2C->I2C_start();
  231.         pSTM32I2C->Delayus(5);
  232.         pSTM32I2C->I2C_send_byte((0X24<<1)|0) ;
  233.   pSTM32I2C->I2C_Wait_Ack_Check();//等待从机收到消息,电平拉低标识

  234.         
  235. /*第二次发送器件内部地址*/        
  236.         pSTM32I2C->Delayus(5);
  237.         pSTM32I2C->I2C_send_byte(0X81);
  238.   pSTM32I2C->I2C_Wait_Ack_Check();//等待从机收到消息,电平拉低标识        

  239.         
  240.   pSTM32I2C->Delayus(5);

  241. /*第三次发送器件物理地址+读命令*/               
  242.         pSTM32I2C->I2C_start();
  243.         pSTM32I2C->Delayus(5);
  244.         pSTM32I2C->I2C_send_byte((0X24<<1)|1) ;               
  245.   pSTM32I2C->I2C_Wait_Ack_Check();//等待从机收到消息,电平拉低标识        


  246.         pSTM32I2C->Delayus(100);
  247. /*前面的代码和前面是一样的。*/        
  248. /*前面0X80是读一个字节一个U8当前按下的值是多少*/        
  249. /*现在我们是读0x81,后面4个字节4个U8*/        
  250.         for(i=0;i<3;i++)
  251.                 pKeyVal[i] = pSTM32I2C->I2C_read_byte(1);
  252.         /*前面3个字节需要ack反馈,最后一个字节就跟前面一样不用反馈*/
  253.         pKeyVal[3]=pSTM32I2C->I2C_read_byte(0);
  254.         
  255.         pSTM32I2C->Delayus(5);
  256.         pSTM32I2C->I2C_stop();        
  257.         return 1;
  258. }
复制代码
  1. #ifndef _HALI2C_H
  2. #define _HALI2C_H
  3. #include "stm32f1xx_hal.h"
  4. #include "tim.h"

  5. ////如果移植程序时只要改一下三个地方就行了
  6. //#define I2C_SCL  GPIO_PIN_6
  7. //#define I2C_SDA  GPIO_PIN_7
  8. //#define GPIO_I2C GPIOB
  9. //#define delay_us TIM3_Delay  

  10. //#define I2C_SCL_H HAL_GPIO_WritePin(GPIO_I2C,I2C_SCL,GPIO_PIN_SET);
  11. //#define I2C_SCL_L HAL_GPIO_WritePin(GPIO_I2C,I2C_SCL,GPIO_PIN_RESET);

  12. //#define I2C_SDA_H HAL_GPIO_WritePin(GPIO_I2C,I2C_SDA,GPIO_PIN_SET)
  13. //#define I2C_SDA_L HAL_GPIO_WritePin(GPIO_I2C,I2C_SDA,GPIO_PIN_RESET)

  14. //void I2C_Init(void);
  15. //void I2C_SDA_OUT(void);
  16. //void I2C_SDA_IN(void);
  17. //void I2C_Start(void);
  18. //void I2C_Stop(void);
  19. //void I2C_Ack(void);
  20. //void I2C_NAck(void);
  21. //unsigned char I2C_Wait_Ack(void);
  22. //void I2C_Send_Byte(unsigned char txd);
  23. //unsigned char I2C_Read_Byte(unsigned char ack);


  24. typedef struct
  25. {
  26.         GPIO_TypeDef *        IICGPIO;
  27.         uint16_t        SCL_PIN;
  28.         uint16_t        SDA_PIN;
  29.         void                                           (*I2C_Init)(void);
  30.         void                                           (*Set_SDA)(void);
  31.         void                                           (*Set_SCL)(void);
  32.         void                                           (*Reset_SDA)(void);
  33.         void                                           (*Reset_SCL)(void);
  34.         unsigned char   (*Get_SDA)(void);
  35.         void                                           (*Delayus)(int Time);
  36.         void            (*Set_SDA_Input_Mode)(void);
  37.         void            (*Set_SDA_Output_Mode)(void);
  38.         void                               (*I2C_start)(void);
  39.         void            (*I2C_stop)(void);
  40.         void            (*I2C_withAck)(void);
  41.         void            (*I2C_withnoAck)(void);
  42.         unsigned char   (*I2C_Wait_Ack_Check)(void);
  43.         unsigned char   (*I2C_read_byte)(unsigned char ack);
  44.         void            (*I2C_send_byte)(unsigned char Byte);
  45. }_STM32I2CHandleType,*STM32I2CHandleType;

  46. void STM32IICInit(void);
  47. char __HTK_I2C_Read_keystatus(unsigned char  *pKeystatus);
  48. char __HTK_I2C_Read_optimal_touch_keyval(unsigned char  *pdwStatus);
  49. #endif
复制代码

和传统的代码是有差别的。
传统的是用宏定义修改(头文件能看到刘洋老师的影子),现在全是函数。
全局变量
_STM32I2CHandleType TemIIC;
STM32I2CHandleType pSTM32I2C=&TemIIC;
一个句柄,一个句柄指针,囊括了IIC所有的 属性。

+++++++++++++++20180611补充+++++++++++今天打开论坛看了一个帖子,发现一个不错的资源:就是自己做按键板。
现在的按键盘是买的嘛,自己做怎么搞呢?
按键的扫描和设计。
矩阵按键扫描资料.rar (3.83 MB, 下载次数: 0)
收藏 1 评论3 发布时间:2018-5-18 11:31

举报

3个回答
与龙共舞 回答时间:2018-5-18 14:15:03
自己又研究了个把小时,脑壳疼。硬件IIC问题先放着真的搞不明白。
现在的问题是:IIC的寄存器的值DR  是正确的它是U32
库函数过去的是U8的数组,挨个赋值。U8=U32这样(应该也是没事的 自动把高位放弃掉吧)
现象确是U8的数组第一个总是0后面的总是一样。

先用模拟的吧
问题.png
勿忘心安110 回答时间:2018-5-18 14:48:18
楼主 厉害 学习了
jy04706985 回答时间:2020-6-24 19:44:10
除了代码量巨大,没看出来有什么优势~~~~~~~~~

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版