1.开发环境 2.说明 3.F4和F1软件IIC区别
GPIO初始化区别
us级延时区别
总结
【STM32的使用|STM32F4软件IIC的使用】1.开发环境:硬件:STM32F407IGH6开发板 任意可使用IIC通讯协议传感器
软件:Keil CubeMX
2.说明:从网店购买了一个IIC通讯模块,网店是提供STM32F103C8T6的开源例程的,从网店上拿到开源例程后本人在F1系列单片机上可以成功跑通,但是换到F4单片机上发现了几个可能影响例程跑通的注意事项,在这里简单说一下
3.F4和F1软件IIC区别:
a.GPIO初始化区别:
SCL --> B10
SDA --> B11
F4上软件IIC初始化代码如下:
GPIO_InitTypeDef GPIO_InitStruct;
__HAL_RCC_GPIOB_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
这里端口我们选择B10 B11作为IIC通讯端口,设置模式为开漏输出,速率为中速,接下来看一下F1上软件IIC初始化代码
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
为了代码看起来更方便,在F1上咱们也选用B10 B11作为IIC通讯端口,设置模式同样是开漏输出,速率为高速, 这里可以看出与F4有明显的不同,因为F4的主频一般为168Mhz,有的甚至达到400Mhz,而IIC最快通讯速度为400Kb/s,F1单片机的主频普遍为72Mhz,在F1单片机上与IIC器件进行通讯时,为了达到更高的通讯频率,通常设定GPIO口为高速模式,但是F4单片机的主频比F1快了一倍甚至更多,如果按照F1的设置同样设定为高频,就会远远超出IIC通讯协议的最高频率,导致无法正常使用软件IIC。
经常使用软件IIC会发现IIC引脚设置有以下的代码,尤其是在F1中:
#define IIC_SDA_IN(){GPIOB->CRH&=0xFFFF0FFF;
GPIOB->CRH|=8<<12;
}
#define IIC_SDA_OUT() {GPIOB->CRH&=0xFFFF0FFF;
GPIOB->CRH|=3<<12;
}
#define IIC_SDA_READGPIOB->IDR&(1<<11)#define IIC_SCL_HHAL_GPIO_WritePin(GPIOB,GPIO_PIN_10,GPIO_PIN_SET)
#define IIC_SCL_LHAL_GPIO_WritePin(GPIOB,GPIO_PIN_10,GPIO_PIN_RESET)
#define IIC_SDA_HHAL_GPIO_WritePin(GPIOB,GPIO_PIN_11,GPIO_PIN_SET)
#define IIC_SDA_LHAL_GPIO_WritePin(GPIOB,GPIO_PIN_11,GPIO_PIN_RESET)
设置IIC通讯端口的高低电平输入输出模式,尤其是以下代码:
#define IIC_SDA_IN(){GPIOB->CRH&=0xFFFF0FFF;
GPIOB->CRH|=8<<12;
}
#define IIC_SDA_OUT() {GPIOB->CRH&=0xFFFF0FFF;
GPIOB->CRH|=3<<12;
}
#define IIC_SDA_READGPIOB->IDR&(1<<11)
在F1中 CRH CRL 代表GPIO口的高8位和低8位,大家都知道STM32GPIO一般有16个I/O口,后面的***&=0xFFFF0FFF***,可以用进制转换器转换一下,这个代表***11111111111111110000111111111111***,每四位代表一个IO口 B11为高8位,从右向左数,正好是第4位(从8开始,第四位正好为11),这段指令的意思是初始化B11 ,分布设定为输入和输出两种模式,但是在F4中,我在F4的GPIO寄存器中并没发现***CRH 和 CRL*** ,当然可能是本人才疏学浅,那该怎么办呢,F1器件的例程直接搬运到F4上会报错啊,其实在F4上更加简单:
#define IIC_SDA_READHAL_GPIO_ReadPin(GPIOB,GPIO_PIN_11)#define IIC_SCL_HHAL_GPIO_WritePin(GPIOB,GPIO_PIN_10,GPIO_PIN_SET)
#define IIC_SCL_LHAL_GPIO_WritePin(GPIOB,GPIO_PIN_10,GPIO_PIN_RESET)
#define IIC_SDA_HHAL_GPIO_WritePin(GPIOB,GPIO_PIN_11,GPIO_PIN_SET)
#define IIC_SDA_LHAL_GPIO_WritePin(GPIOB,GPIO_PIN_11,GPIO_PIN_RESET)
使用以上代码,再把手中F1的IIC协议中出现的以下代码注释掉即可:
// IIC_SDA_IN();
//SDA设置为输入
// IIC_SDA_OUT();
//SDA线输出
就能正常使用了,这里就先不粘贴IIC通讯协议的底层程序了,比如正点原子、野火、硬石科技等STM32嵌入式教程中的例程里面有关软件IIC或者说模拟IIC的使用有很多了,并且各家教程基本上大同小异.
b.us级别的延时的区别,之前咱们提到IIC的最快通讯速度是400Kb/s,所以在F1上和F4上如果都使用us级别的软件延时代码是不同的,但是咱们所购买的大部分IIC通讯模块都是针对F1系列单片机所写的软件延时,但是如果直接搬到F4上是无法直接使用的,或者说即使能够使用,也会降低IIC的通讯速度,这里给大家奉上一个使用基本定时器7的延时程序,直接倒库添加初始化完毕后即可使用:
delay.c
#include "delay.h"TIM_HandleTypeDef htim7;
void MX_TIM7_Init(void)
{/* USER CODE BEGIN TIM7_Init 0 *//* USER CODE END TIM7_Init 0 */TIM_MasterConfigTypeDef sMasterConfig = {0};
htim7.Instance = TIM7;
htim7.Init.Prescaler = 0;
htim7.Init.CounterMode = TIM_COUNTERMODE_UP;
htim7.Init.Period = 65535;
htim7.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim7) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim7, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
}
void delay_init()
{
MX_TIM7_Init();
__HAL_TIM_ENABLE(&htim7);
}
void delay_us(u32 nus){
__HAL_TIM_SetCounter(&htim7, 0);
while(__HAL_TIM_GetCounter(&htim7) < (42 * nus));
//TIM7挂载在APB1的peripheral时钟线,时钟为42Mhz
__HAL_TIM_SetCounter(&htim7, 0);
while(__HAL_TIM_GetCounter(&htim7) < (42 * nus));
//TIM7挂载在APB1的peripheral时钟线,时钟为42Mhz
return;
}
delay.h
#ifndef __DELAY_H
#define __DELAY_H
#include#define delay_ms(i) HAL_Delay(i)extern TIM_HandleTypeDef htim7;
void MX_TIM7_Init(void);
void delay_init(void);
void delay_us(u32);
#endif
在软件IIC中的us级别延时直接调用函数即可,这里的程序是F4中的代码,F1的话需要注意时钟挂载的总线频率。
c.总结:以上是我在测试软件IIC通讯的时候发现的F1和F4之间的区别,说的并不全面欢迎大神来补充,但是涉及到的坑,我能想到的目前只有这些,如果大家有想法欢迎大家留言评论,谢谢!
推荐阅读
- 嵌入式|CAN通讯
- stm32|基于stm32f103与IIC的0.96OLED屏幕显示字符与平滑滚动显示
- 嵌入式|STM32 0.96寸4针IOLED显示器驱动IIC(HAL库)
- stm32|STM32Cubemx——IIC驱动0.96寸OLED
- stm32|基于I2C/SPI总线的温湿度采集与OLED显示
- 嵌入式|STM32 0.96寸OLED IIC通信
- oled模块学习|OLED_I2C_SH1106屏幕教程
- STM32|STM32控制0.96寸OLED(4针/4Pin)汉字以及数字,英文显示
- stm32|基于STM32的智能家具控制系统(ESP-01S(8266)、手机app远程控制、远程显示温度)