目录
2.4 在i2c.c中重新定义stm32f1xx_hal_i2c.h中的两个函数
一、IIC轮询模式
1.1 配置
不确认IIC有没有硬件上拉,保险起见,将SCL SDA的GPIO设置为上拉
1.2 编写AHT20驱动
根据AHT20手册编写初始化与读数据函数
1.2.1 aht20.h
#ifndef INC_AHT20_H_
#define INC_AHT20_H_
#include "i2c.h"
void AHT20_Init();
void AHT20_Read(float* Temperature,float* Humidity);
#endif /* INC_AHT20_H_ */
1.2.2 aht20.c
#include "aht20.h"
#define AHT20_ADDRESS 0x70
void AHT20_Init()
{
uint8_t readBuffer;
HAL_Delay(40);
HAL_I2C_Master_Receive(&hi2c1,AHT20_ADDRESS,&readBuffer,1,HAL_MAX_DELAY);
if((readBuffer& 0x80)==0x00)
{
uint8_t sendBuffer[3]={0xBE,0x80,0x00};
HAL_I2C_Master_Transmit(&hi2c1, AHT20_ADDRESS, sendBuffer, 3, HAL_MAX_DELAY);
}
}
void AHT20_Read(float* Temperature,float* Humidity)
{
uint8_t sendBuffer[3] = {0xAC,0x33,0x00};
uint8_t readBuffer[6];
HAL_I2C_Master_Transmit(&hi2c1, AHT20_ADDRESS, sendBuffer, 3, HAL_MAX_DELAY);
HAL_Delay(75);
HAL_I2C_Master_Receive(&hi2c1,AHT20_ADDRESS,readBuffer,6,HAL_MAX_DELAY);
if((readBuffer[0] & 0x80)== 0x00)
{
uint32_t date = 0;
date=(((uint32_t)readBuffer[3]>>4) + ((uint32_t)readBuffer[2]<<4) + ((uint32_t)readBuffer[1]<<12));
*Humidity = date * 100.0f/(1<<20);
date=(((uint32_t)readBuffer[3]&0x0F)<<16) + ((uint32_t)readBuffer[4]<<8) + (uint32_t)readBuffer[5];
*Temperature = date * 200.0f/(1<<20)-50;
}
}
二、I2C中断
2.1 打开中断
2.2 分离读取流程
分为测量指令 读取指令 解析 三部分
void AHT20_Measure()
{
static uint8_t sendBuffer[3] = {0xAC,0x33,0x00};
HAL_I2C_Master_Transmit_IT(&hi2c1, AHT20_ADDRESS, sendBuffer, 3);
}
void AHT20_Get()
{
HAL_I2C_Master_Receive_IT(&hi2c1,AHT20_ADDRESS,readBuffer,6);
}
void AHT20_Analysis(float* Temperature,float* Humidity)
{
if((readBuffer[0] & 0x80)== 0x00)
{
uint32_t date = 0;
date=(((uint32_t)readBuffer[3]>>4) + ((uint32_t)readBuffer[2]<<4) + ((uint32_t)readBuffer[1]<<12));
*Humidity = date * 100.0f/(1<<20);
date=(((uint32_t)readBuffer[3]&0x0F)<<16) + ((uint32_t)readBuffer[4]<<8) + (uint32_t)readBuffer[5];
*Temperature = date * 200.0f/(1<<20)-50;
}
}
2.3 在主函数中重新编写读取流程
if(aht20State==0)
{
AHT20_Measure();
aht20State=1;
}else if(aht20State==2)
{
HAL_Delay(75);
AHT20_Get();
aht20State=3;
}else if(aht20State==4)
{
AHT20_Analysis(&temperature, &humidity);
sprintf(message,"温度�? %.1f �?, 湿度�?%.1f %%\r\n",temperature,humidity);
HAL_UART_Transmit(&huart1, (uint8_t*)message, strlen(message), HAL_MAX_DELAY);
HAL_Delay(1000);
aht20State=0;
}
2.4 在i2c.c中重新定义stm32f1xx_hal_i2c.h中的两个函数
// 发送完成时回调
void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c)
{
if(hi2c==&hi2c1)
{
aht20State=2;
}
}
void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c)
{
if(hi2c==&hi2c1)
{
aht20State=4;
}
}
三、I2CDMA
3.1 配置DMA通道
从机配置如下,DMA模式也需要开启中断。从机地址配置为0x15,7位地址加1位读写位,从机写命令就为0x2A
主机配置与从机相同,只是不配置从机地址。
3.2 代码
从机代码
/* Infinite loop */
/* USER CODE BEGIN WHILE */
HAL_I2C_Slave_Receive_DMA(&hi2c3, readBuffer, 1);
while (1)
{
HAL_GPIO_TogglePin(LED3_GPIO_Port, LED3_Pin);
HAL_Delay(500);
//HAL_I2C_Master_Transmit_DMA(&hi2c1, 0x2A, sendBuffer, sizeof(sendBuffer));
/* USER CODE END WHILE */
}
//I2C1_DMA_Read callback function
void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c)
{
printf("SlaveRxCpltCallback begin data: %d\r\n",readBuffer[0]);
HAL_I2C_Slave_Receive_DMA(&hi2c3, readBuffer, 1);
}
主机代码
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
if(HAL_I2C_Master_Transmit_DMA(&hi2c1, 0x2A, sendBuffer, sizeof(sendBuffer))!=HAL_OK)
printf("HAL_I2C_Master_Transmit_DMA error \r\n");
else
printf("sendData %d finish \r\n",sendBuffer[0]);
HAL_Delay(1000);
/* USER CODE END WHILE */
}
void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c)
{
sendBuffer[0]++;
}
四、LL库中断接收
4.1 配置
从机地址0x15,7位地址,移位后加上读写位,写指令就为0x2A
中断开启,GPIO也要最好设置为上拉
4.2 代码
开中断与数据处理
...
LL_I2C_EnableIT_ADDR(I2C3);
LL_I2C_EnableIT_NACK(I2C3);
LL_I2C_EnableIT_ERR(I2C3);
LL_I2C_EnableIT_STOP(I2C3);
...
while (1)
{
if(1 == Flag_I2C_FrontBackSystem)
{
printf("Start while !\r\n");
allocate_task(RegisterIndex);
Flag_I2C_FrontBackSystem = 0;
}
printf("data 0x%x,%d!!!!!!\r\n",RegisterMap[0],Flag_I2C_FrontBackSystem);
}
...
void allocate_task(uint16_t index)
{
switch (index)
{
case 0x00:
{
uint16_t Flag_Mode = RegisterMap[index];
if(Flag_Mode == 0x11)
{
printf("IIC3 Receive 0x11\r\n");
}
}
break;
case 0x01:
{
}
break;
default:
break;
}
}
在事件中断中调用回调函数
void I2C3_EV_IRQHandler(void)
{
/* USER CODE BEGIN I2C3_EV_IRQn 0 */
I2C_EV_Callback(I2C3);
/* USER CODE END I2C3_EV_IRQn 0 */
/* USER CODE BEGIN I2C3_EV_IRQn 1 */
/* USER CODE END I2C3_EV_IRQn 1 */
}
回调函数
/*
I2C3 Slave Function
I2C3 set as slave device to communicate with Dothink
*/
void I2C_EV_Callback(I2C_TypeDef *I2Cx)
{
/*Check ADDR Flag,EV1*/
if(LL_I2C_IsActiveFlag_ADDR(I2Cx))
{
if(LL_I2C_GetTransferDirection(I2Cx) == LL_I2C_DIRECTION_WRITE)
{
Flag_I2C_Slave_Internal = 1;
LL_I2C_ClearFlag_ADDR(I2Cx);
LL_I2C_EnableIT_RX(I2Cx);
}
else if(LL_I2C_GetTransferDirection(I2Cx) == LL_I2C_DIRECTION_READ)
{
LL_I2C_ClearFlag_ADDR(I2Cx);
LL_I2C_EnableIT_TX(I2Cx);
}
else
LL_I2C_ClearFlag_ADDR(I2Cx);
}
/*Check RXNE Flag,EV2*/
if(LL_I2C_IsActiveFlag_RXNE(I2Cx))
{
if(Flag_I2C_Slave_Internal == 1)
{
RegisterIndex = LL_I2C_ReceiveData8(I2Cx);
Flag_I2C_Slave_Internal = 2;
}
else if(Flag_I2C_Slave_Internal == 2)
{
RegisterMap[RegisterIndex]=LL_I2C_ReceiveData8(I2Cx);
Flag_I2C_FrontBackSystem = 1; //front back system flag
}
}
/*Check NACK Flag,EV3-2*/
if(LL_I2C_IsActiveFlag_NACK(I2Cx))
{
LL_I2C_ClearFlag_NACK(I2Cx);
Flag_I2C_Slave_Internal = 0;
}
/*Check TXE Flag,EV3-1,EV3*/
if(LL_I2C_IsActiveFlag_TXIS(I2Cx))
LL_I2C_TransmitData8(I2Cx, RegisterMap[RegisterIndex++]); //support continus read
/*Check STOP Flag,EV4*/
if(LL_I2C_IsActiveFlag_STOP(I2Cx))
{
LL_I2C_ClearFlag_STOP(I2Cx);
if(!LL_I2C_IsActiveFlag_TXE(I2Cx))
LL_I2C_ClearFlag_TXE(I2Cx);
Flag_I2C_Slave_Internal = 0;
}
}
//I2C1_DMA_Write callback function
void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *hi2c)
{
}
//I2C1_DMA_Read callback function
void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c)
{
}