本帖最后由 与龙共舞 于 2018-6-11 09:17 编辑
这是最后一篇。自己昨天完成的一个工程,终于自己动手写出了人人喊打的代码。
+++++++++++++项目介绍++++++++++++++++
逛论坛时间不长,新人,偶然看到@游名 发帖子免费申请按键板,我就参加了。
其实我公司也有做门禁的,我也是公司新人,业务不懂,就先玩玩吧。
货到付款,相当于15块钱买了一个小板子。
提供的资料很全,有历程代码,有规格书。
+++++++++++框架介绍++++++++++++++++
工作逻辑:按键板一共6个脚连接到STM32主控板
1上电(不管)
2接地(不管)
3复位(就是接到STM32的一个GPIO,先拉高在拉低在拉高就可以让这个按键板复位一次)
4中断 (也是接到STM32的一个GPIO,当有按键被按的时候这个电平会突然拉高,也就触发了中断线。然后你去就IIC总线读数据)
5(IIC SDA)
6 (IIC SCL)
所以主要知识点是:A中断线(类似于很多教程里面的按键触发LED灯亮起)B IIC通讯(类似有ATC02存储的教程)
++++++++开始吧+++++++++++
后面的配置都没有修改。(用了一个TIM定时器来做延时)
基于cubemx+硬件IIC 几分钟就跑通了。
很快问题也就来了。(反馈给HTK公司技术的视频)
https://pan.baidu.com/s/10pr82ORcf4lanSPKwMdPHw
数据是00-32-32-32,虽然可以用,但有点膈应。
于是打算放弃硬件IIC,自己也来模拟IIC吧。
所以回到标题:机器风格的单片机程序
- #include "HALI2C.h"
- _STM32I2CHandleType TemIIC;
- STM32I2CHandleType pSTM32I2C=&TemIIC;
- /*初始化 时钟 GPIO 两线都高*/
- void I2C_init(void)
- {
- GPIO_InitTypeDef GPIO_InitStruct;
- __HAL_RCC_GPIOD_CLK_ENABLE();
- __HAL_RCC_GPIOA_CLK_ENABLE();
- __HAL_RCC_GPIOB_CLK_ENABLE();
- GPIO_InitStruct.Pin=pSTM32I2C->SCL_PIN|pSTM32I2C->SDA_PIN;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
- GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;/*推荐复用输出*/
- HAL_GPIO_Init(pSTM32I2C->IICGPIO, &GPIO_InitStruct);
- pSTM32I2C->Set_SDA();
- pSTM32I2C->Set_SCL();
- }
- /*设置SDA为输出模式*/
- void I2C_SDA_OUT(void)
- {
- GPIO_InitTypeDef GPIO_InitStruct;
-
- GPIO_InitStruct.Pin=pSTM32I2C->SCL_PIN|pSTM32I2C->SDA_PIN;
- GPIO_InitStruct.Speed=GPIO_SPEED_FREQ_HIGH;
- GPIO_InitStruct.Mode=GPIO_MODE_OUTPUT_PP;
- HAL_GPIO_Init(pSTM32I2C->IICGPIO, &GPIO_InitStruct);
- }
- /*设置SDA为输入模式*/
- void I2C_SDA_IN(void)
- {
- GPIO_InitTypeDef GPIO_InitStruct;
-
- GPIO_InitStruct.Pin=pSTM32I2C->SDA_PIN;
- GPIO_InitStruct.Mode=GPIO_MODE_INPUT;
- HAL_GPIO_Init(pSTM32I2C->IICGPIO, &GPIO_InitStruct);
- }
- /*产生起始信号*/
- void I2C_Start(void)
- {
- pSTM32I2C->Set_SDA_Output_Mode();
- pSTM32I2C->Set_SDA();
- pSTM32I2C->Set_SCL();
- pSTM32I2C->Delayus(5);
- pSTM32I2C->Reset_SDA();
- pSTM32I2C->Delayus(5);
- pSTM32I2C->Reset_SCL();
- pSTM32I2C->Delayus(5);
- }
- /*产生停止信号*/
- void I2C_Stop(void)
- {
- pSTM32I2C->Set_SDA_Output_Mode();
- pSTM32I2C->Reset_SCL();
- pSTM32I2C->Reset_SDA();
- pSTM32I2C->Set_SCL();
- pSTM32I2C->Delayus(6);
- pSTM32I2C->Set_SDA();
- pSTM32I2C->Delayus(6);
- }
- //主机产生应答信号ACK
- void I2C_Ack(void)
- {
- pSTM32I2C->Reset_SCL();
- pSTM32I2C->Delayus(2);
- pSTM32I2C->Set_SDA_Output_Mode();
- pSTM32I2C->Reset_SDA();
- pSTM32I2C->Delayus(5);
- pSTM32I2C->Set_SCL();
- pSTM32I2C->Delayus(5);
- pSTM32I2C->Reset_SCL();
- }
- //主机不产生应答信号NACK
- void I2C_NAck(void)
- {
- pSTM32I2C->Reset_SCL();
- pSTM32I2C->Delayus(2);
- pSTM32I2C->Set_SDA_Output_Mode();
- pSTM32I2C->Set_SDA();
- pSTM32I2C->Delayus(5);
- pSTM32I2C->Set_SCL();
- pSTM32I2C->Delayus(5);
- pSTM32I2C->Reset_SCL();
- pSTM32I2C->Delayus(2);
- }
- //等待从机应答信号
- //返回值:1 接收应答失败
- // 0 接收应答成功
- unsigned char I2C_Wait_Ack(void)
- {
- unsigned char tempTime=0;
- pSTM32I2C->Set_SDA_Input_Mode();
- pSTM32I2C->Set_SDA();
- pSTM32I2C->Delayus(5);
- pSTM32I2C->Set_SCL();
- pSTM32I2C->Delayus(2);
- while(pSTM32I2C->Get_SDA())
- {
- tempTime++;
- if(tempTime>50)
- {
- pSTM32I2C->I2C_stop();
- return 0;
- }
- }
- pSTM32I2C->Reset_SCL();
- pSTM32I2C->Delayus(5);
- return 1;
- }
- //I2C 发送一个字节
- void I2C_Send_Byte(unsigned char txd)
- {
- unsigned char i=0;
- pSTM32I2C->Set_SDA_Output_Mode();
- pSTM32I2C->Reset_SCL();//拉低时钟开始数据传输
- for(i=0;i<8;i++)
- {
- if((txd<<i)&0x80)
- pSTM32I2C->Set_SDA();
- else
- pSTM32I2C->Reset_SDA();
-
- pSTM32I2C->Delayus(2);
- pSTM32I2C->Set_SCL();
- pSTM32I2C->Delayus(5); //发送数据
- pSTM32I2C->Reset_SCL();
- pSTM32I2C->Delayus(2);
- }
- }
- //I2C 读取一个字节
- unsigned char I2C_Read_Byte(unsigned char ack)
- {
- unsigned char i=0,receive=0;
- pSTM32I2C->Set_SDA_Input_Mode();
- for(i=0;i<8;i++)
- {
- pSTM32I2C->Reset_SCL();
- pSTM32I2C->Delayus(5);
- pSTM32I2C->Set_SCL();
- receive<<=1;
- if(pSTM32I2C->Get_SDA())
- receive++;
- pSTM32I2C->Delayus(5);
- }
- if(ack==0)
- pSTM32I2C->I2C_withnoAck();
- else
- pSTM32I2C->I2C_withAck();
- return receive;
- }
- void set_SDA(void)
- {
- HAL_GPIO_WritePin(pSTM32I2C->IICGPIO,pSTM32I2C->SDA_PIN,GPIO_PIN_SET);
- }
- void set_SCL(void)
- {
- HAL_GPIO_WritePin(pSTM32I2C->IICGPIO,pSTM32I2C->SCL_PIN,GPIO_PIN_SET);
- }
- void reset_SDA(void)
- {
- HAL_GPIO_WritePin(pSTM32I2C->IICGPIO,pSTM32I2C->SDA_PIN,GPIO_PIN_RESET);
- }
- void reset_SCL(void)
- {
- HAL_GPIO_WritePin(pSTM32I2C->IICGPIO,pSTM32I2C->SCL_PIN,GPIO_PIN_RESET);
- }
- unsigned char read_SDAPIN(void)
- {
- return HAL_GPIO_ReadPin(pSTM32I2C->IICGPIO,pSTM32I2C->SDA_PIN);
- }
- ///////////////////设备驱动//////////////////////
- void STM32IICInit(void)
- {
- _STM32I2CHandleType temIIC=
- {
- .IICGPIO=GPIOB,
- .SCL_PIN=GPIO_PIN_6,
- .SDA_PIN=GPIO_PIN_7,
- .I2C_Init=I2C_init,
- .Set_SDA=set_SDA,
- .Set_SCL=set_SCL,
- .Reset_SDA=reset_SDA,
- .Reset_SCL=reset_SCL,
- .Get_SDA=read_SDAPIN,
- .Delayus=TIM3_Delay,
- .Set_SDA_Input_Mode=I2C_SDA_IN,
- .Set_SDA_Output_Mode=I2C_SDA_OUT,
- .I2C_start=I2C_Start,
- .I2C_stop=I2C_Stop,
- .I2C_withAck=I2C_Ack,
- .I2C_withnoAck=I2C_NAck,
- .I2C_Wait_Ack_Check=I2C_Wait_Ack,
- .I2C_read_byte=I2C_Read_Byte,
- .I2C_send_byte=I2C_Send_Byte,
- };
- TemIIC=temIIC;/*做了一个临时变量 然后用=号做了赋值*/
- pSTM32I2C->I2C_Init();
- }
- +++++++++++++++++++噢这不好 可以直接赋值的int a=9这样直接全局变量赋值+++++++++++++
- char __HTK_I2C_Read_optimal_touch_keyval(unsigned char *pKeyVal)
- {
- /*第一次发送器件物理地址+写命令*/
- pSTM32I2C->I2C_start();
- pSTM32I2C->Delayus(5);
- pSTM32I2C->I2C_send_byte((0X24<<1)|0) ;
- pSTM32I2C->I2C_Wait_Ack_Check();//等待从机收到消息,电平拉低标识
-
- /*第二次发送器件内部地址*/
- pSTM32I2C->Delayus(5);
- pSTM32I2C->I2C_send_byte(0X80);
- pSTM32I2C->I2C_Wait_Ack_Check();//等待从机收到消息,电平拉低标识
-
- pSTM32I2C->Delayus(5);
- /*第三次发送器件物理地址+读命令*/
- pSTM32I2C->I2C_start();
- pSTM32I2C->Delayus(5);
- pSTM32I2C->I2C_send_byte((0X24<<1)|1) ;
- pSTM32I2C->I2C_Wait_Ack_Check();//等待从机收到消息,电平拉低标识
- pSTM32I2C->Delayus(100);
- /*读取反馈数据 因为只读一个字节 所以不需要ack反馈信号*/
- *pKeyVal = pSTM32I2C->I2C_read_byte(0);
-
- pSTM32I2C->Delayus(5);
- pSTM32I2C->I2C_stop();
- return 1;
- }
-
-
- char __HTK_I2C_Read_keystatus(unsigned char *pKeyVal)
- {
- char i=0;
- /*第一次发送器件物理地址+写命令*/
- pSTM32I2C->I2C_start();
- pSTM32I2C->Delayus(5);
- pSTM32I2C->I2C_send_byte((0X24<<1)|0) ;
- pSTM32I2C->I2C_Wait_Ack_Check();//等待从机收到消息,电平拉低标识
-
- /*第二次发送器件内部地址*/
- pSTM32I2C->Delayus(5);
- pSTM32I2C->I2C_send_byte(0X81);
- pSTM32I2C->I2C_Wait_Ack_Check();//等待从机收到消息,电平拉低标识
-
- pSTM32I2C->Delayus(5);
- /*第三次发送器件物理地址+读命令*/
- pSTM32I2C->I2C_start();
- pSTM32I2C->Delayus(5);
- pSTM32I2C->I2C_send_byte((0X24<<1)|1) ;
- pSTM32I2C->I2C_Wait_Ack_Check();//等待从机收到消息,电平拉低标识
- pSTM32I2C->Delayus(100);
- /*前面的代码和前面是一样的。*/
- /*前面0X80是读一个字节一个U8当前按下的值是多少*/
- /*现在我们是读0x81,后面4个字节4个U8*/
- for(i=0;i<3;i++)
- pKeyVal[i] = pSTM32I2C->I2C_read_byte(1);
- /*前面3个字节需要ack反馈,最后一个字节就跟前面一样不用反馈*/
- pKeyVal[3]=pSTM32I2C->I2C_read_byte(0);
-
- pSTM32I2C->Delayus(5);
- pSTM32I2C->I2C_stop();
- return 1;
- }
复制代码- #ifndef _HALI2C_H
- #define _HALI2C_H
- #include "stm32f1xx_hal.h"
- #include "tim.h"
- ////如果移植程序时只要改一下三个地方就行了
- //#define I2C_SCL GPIO_PIN_6
- //#define I2C_SDA GPIO_PIN_7
- //#define GPIO_I2C GPIOB
- //#define delay_us TIM3_Delay
- //#define I2C_SCL_H HAL_GPIO_WritePin(GPIO_I2C,I2C_SCL,GPIO_PIN_SET);
- //#define I2C_SCL_L HAL_GPIO_WritePin(GPIO_I2C,I2C_SCL,GPIO_PIN_RESET);
- //#define I2C_SDA_H HAL_GPIO_WritePin(GPIO_I2C,I2C_SDA,GPIO_PIN_SET)
- //#define I2C_SDA_L HAL_GPIO_WritePin(GPIO_I2C,I2C_SDA,GPIO_PIN_RESET)
- //void I2C_Init(void);
- //void I2C_SDA_OUT(void);
- //void I2C_SDA_IN(void);
- //void I2C_Start(void);
- //void I2C_Stop(void);
- //void I2C_Ack(void);
- //void I2C_NAck(void);
- //unsigned char I2C_Wait_Ack(void);
- //void I2C_Send_Byte(unsigned char txd);
- //unsigned char I2C_Read_Byte(unsigned char ack);
- typedef struct
- {
- GPIO_TypeDef * IICGPIO;
- uint16_t SCL_PIN;
- uint16_t SDA_PIN;
- void (*I2C_Init)(void);
- void (*Set_SDA)(void);
- void (*Set_SCL)(void);
- void (*Reset_SDA)(void);
- void (*Reset_SCL)(void);
- unsigned char (*Get_SDA)(void);
- void (*Delayus)(int Time);
- void (*Set_SDA_Input_Mode)(void);
- void (*Set_SDA_Output_Mode)(void);
- void (*I2C_start)(void);
- void (*I2C_stop)(void);
- void (*I2C_withAck)(void);
- void (*I2C_withnoAck)(void);
- unsigned char (*I2C_Wait_Ack_Check)(void);
- unsigned char (*I2C_read_byte)(unsigned char ack);
- void (*I2C_send_byte)(unsigned char Byte);
- }_STM32I2CHandleType,*STM32I2CHandleType;
- void STM32IICInit(void);
- char __HTK_I2C_Read_keystatus(unsigned char *pKeystatus);
- char __HTK_I2C_Read_optimal_touch_keyval(unsigned char *pdwStatus);
- #endif
复制代码
和传统的代码是有差别的。
传统的是用宏定义修改(头文件能看到刘洋老师的影子),现在全是函数。
全局变量
_STM32I2CHandleType TemIIC;
STM32I2CHandleType pSTM32I2C=&TemIIC;
一个句柄,一个句柄指针,囊括了IIC所有的 属性。
+++++++++++++++20180611补充+++++++++++今天打开论坛看了一个帖子,发现一个不错的资源:就是自己做按键板。
现在的按键盘是买的嘛,自己做怎么搞呢?
按键的扫描和设计。
矩阵按键扫描资料.rar
(3.83 MB, 下载次数: 0)
|
现在的问题是:IIC的寄存器的值DR 是正确的它是U32
库函数过去的是U8的数组,挨个赋值。U8=U32这样(应该也是没事的 自动把高位放弃掉吧)
现象确是U8的数组第一个总是0后面的总是一样。
埃
先用模拟的吧