本文主要是介绍pal库 IIC,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
数据接收的流程
下面的流程可以用一个接口来实现 一个函数接口
第一个就是从机的地址 第二个参数就是接收数据的缓冲区 第三个参数就是 接收数据的大小
RXNE和BTF标志位
当两个寄存器(TDR)和移位寄存器都满的时候标志位BTF就为1 表示缓冲区已满
ACK和ANK的发送
在之前都是主机发送数据 从机回复ACK或者NAK信号表示信号接收完毕 到数据的接收就反过来了 就是主机回复ACK或者NAK信号
CR寄存器的一个标志位 来控制发送的是ACK还是NAK信号
停止位的发送
向状态寄存器的STOP位写1 如果有数据正在接收那么就会在接受完这个数据后才会发送停止位
发送起始位和地址位
首先查询IIC总线是否空闲 第一个while 然后发送一个起始位 然后查询是否发送成功第二个while 然后发送从机地址 |0x01是为了保证最后一位为1 表示是主机接收数据 从机发送数据 接收操作
发送从机地址前首先要清除AF标志位 然后发送地址
查询ADDR标志位查看是否寻址成功 如果寻址成功然后再查询AF标志位如果也等于1 那么说明寻址失败了 然后发送停止信号 结束 (往标志位STOP中写值发送停止信号) 等待总线空闲返回错误
接收数据 N=1
首先要清除ADDR标志位才可以传入数据
接受数据 N=2
接收数据 N>2
从倒数第三个数据开始 前N-3个数据都是一样的读取到缓冲区 然后到倒数第三个和倒数第二个数据进入RDR寄存器和移位寄存器 两个寄存器都满了然后标志位BTF为1 把两个数据都读取出来然后最后一个数据在传输进来的时候写入NCK和停止位结束数据的传输
测试
当熄灭显示器数据就是01000000 然后接收数据就是0x40 接收一个字节 接收两个字节就是两个0x40 接收八个字节就是8个0x40
亮起就都是0x00
#include "stm32f10x.h"
#include "stm32f10x_pal.h"static void App_I2C_Init(void);
static ErrorStatus App_I2C_MasterTransmit(uint8_t SlaveAddr, const uint8_t *pData, uint16_t Size);
static ErrorStatus App_I2C_MasterReceive(uint8_t SlaveAddr, uint8_t *pDataOut, uint16_t Size); //接收数据int main(void)
{PAL_Init();App_I2C_Init();const uint8_t oled_init_command[] = {0x00, // Data Stream0xa8, 0x3f, // Set MUX Ratio0xd3, 0x00, // Set Display Offset 0x40, // Set Display Start Line0xa0, // Set Segment re-map0xc0, // Set COM Output Scan Direction0xda, 0x02, // Set COM Pins hardware configuration0x81, 0x7f, // Set Contrast Control0xa5, // Enable Entire Display On0xa6, // Set Normal Display0xd5, 0x80, // Set OSC Frequency0x8d, 0x14, // Enable charge pump regulator0xaf, // Display on}; App_I2C_MasterTransmit(0x78, oled_init_command, sizeof(oled_init_command)/sizeof(uint8_t));const uint8_t oled_display_off_command[] = {0x00, 0xae};const uint8_t oled_display_on_command[] = {0x00, 0xaf};uint8_t buffer[8];// 熄灭屏幕App_I2C_MasterTransmit(0x78, oled_display_off_command, sizeof(oled_display_off_command)/sizeof(uint8_t));App_I2C_MasterReceive(0x78, buffer, 1);App_I2C_MasterReceive(0x78, buffer, 2);App_I2C_MasterReceive(0x78, buffer, 8);App_I2C_MasterTransmit(0x78, oled_display_on_command, sizeof(oled_display_on_command)/sizeof(uint8_t));App_I2C_MasterReceive(0x78, buffer, 1);App_I2C_MasterReceive(0x78, buffer, 2);App_I2C_MasterReceive(0x78, buffer, 8);while(1){}
}static void App_I2C_Init(void)
{// #1. 初始化SCL和SDA引脚RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStruct);// #2. 为I2C1开启时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, ENABLE);RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, DISABLE);// #3. 配置I2C的参数I2C_InitTypeDef I2C_InitStruct;I2C_InitStruct.I2C_ClockSpeed = 400000;I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;// I2C_InitStruct.I2C_OwnAddress1 = 0x12;// I2C_InitStruct.I2C_Ack = I2C_Ack_Disable;// I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;I2C_Init(I2C1, &I2C_InitStruct);// #4. 使能I2CI2C_Cmd(I2C1, ENABLE);
}static ErrorStatus App_I2C_MasterTransmit(uint8_t SlaveAddr, const uint8_t *pData, uint16_t Size)
{ // #1. 等待总线空闲while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) == SET);// #2. 发送起始位I2C_GenerateSTART(I2C1, ENABLE);while(I2C_GetFlagStatus(I2C1, I2C_FLAG_SB) == RESET);// #3. 发送从机地址I2C_ClearFlag(I2C1, I2C_FLAG_AF);I2C_SendData(I2C1, SlaveAddr & 0xfe);while(I2C_GetFlagStatus(I2C1, I2C_FLAG_ADDR) == RESET){if(I2C_GetFlagStatus(I2C1, I2C_FLAG_AF) == SET){goto TAG_ERROR;}}I2C_ReadRegister(I2C1, I2C_Register_SR1);I2C_ReadRegister(I2C1, I2C_Register_SR2);// #4. 发送数据uint32_t i;for(i=0;i<Size;i++){while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TXE) == RESET){if(I2C_GetFlagStatus(I2C1, I2C_FLAG_AF) == SET){goto TAG_ERROR;}}I2C_SendData(I2C1, pData[i]);}while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF) == RESET){if(I2C_GetFlagStatus(I2C1, I2C_FLAG_AF) == SET){goto TAG_ERROR;}}// #5. 发送停止位I2C_GenerateSTOP(I2C1, ENABLE);return SUCCESS;TAG_ERROR:I2C_GenerateSTOP(I2C1, ENABLE);return ERROR;
}static ErrorStatus App_I2C_MasterReceive(uint8_t SlaveAddr, uint8_t *pDataOut, uint16_t Size)
{if(Size == 0){return ERROR;}// #1. 等待总线空闲while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) == SET);// #2. 发送起始位I2C_GenerateSTART(I2C1, ENABLE);while(I2C_GetFlagStatus(I2C1, I2C_FLAG_SB) == RESET); // #3. 发送从机地址I2C_ClearFlag(I2C1, I2C_FLAG_AF);I2C_SendData(I2C1, SlaveAddr | 0x01);while(I2C_GetFlagStatus(I2C1, I2C_FLAG_ADDR) == RESET){if(I2C_GetFlagStatus(I2C1, I2C_FLAG_AF) == SET){goto TAG_ERROR;}}// #4. 接收数据I2C_AcknowledgeConfig(I2C1, ENABLE);I2C_NACKPositionConfig(I2C1, I2C_NACKPosition_Current);if(Size == 1){I2C_ReadRegister(I2C1, I2C_Register_SR1);I2C_ReadRegister(I2C1, I2C_Register_SR2);I2C_AcknowledgeConfig(I2C1, DISABLE);I2C_NACKPositionConfig(I2C1, I2C_NACKPosition_Current);I2C_GenerateSTOP(I2C1, ENABLE);while(I2C_GetFlagStatus(I2C1, I2C_FLAG_RXNE)==RESET);pDataOut[0] = I2C_ReceiveData(I2C1);}else if(Size == 2){I2C_AcknowledgeConfig(I2C1, ENABLE);I2C_ReadRegister(I2C1, I2C_Register_SR1);I2C_ReadRegister(I2C1, I2C_Register_SR2);while(I2C_GetFlagStatus(I2C1, I2C_FLAG_RXNE) == RESET);I2C_AcknowledgeConfig(I2C1, DISABLE);I2C_GenerateSTOP(I2C1, ENABLE);while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF) == RESET);pDataOut[0] = I2C_ReceiveData(I2C1);pDataOut[1] = I2C_ReceiveData(I2C1);}else{uint32_t i;I2C_ReadRegister(I2C1, I2C_Register_SR1);I2C_ReadRegister(I2C1, I2C_Register_SR2);for(i=0;i<Size-3;i++){while(I2C_GetFlagStatus(I2C1, I2C_FLAG_RXNE) == RESET);pDataOut[i] = I2C_ReceiveData(I2C1);}while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF) == RESET);I2C_AcknowledgeConfig(I2C1, DISABLE);pDataOut[Size-3] = I2C_ReceiveData(I2C1);I2C_GenerateSTOP(I2C1, ENABLE);pDataOut[Size-2] = I2C_ReceiveData(I2C1);while(I2C_GetFlagStatus(I2C1, I2C_FLAG_RXNE) == RESET);pDataOut[Size-1] = I2C_ReceiveData(I2C1);}return SUCCESS;
TAG_ERROR:I2C_GenerateSTOP(I2C1, ENABLE);return ERROR;
}
PAL库函数接口
#include "stm32f10x.h"
#include "stm32f10x_pal.h"
#include "stm32f10x_pal_i2c.h"static void App_I2C_Init(void);
static ErrorStatus App_I2C_MasterTransmit(uint8_t SlaveAddr, const uint8_t *pData, uint16_t Size);
static ErrorStatus App_I2C_MasterReceive(uint8_t SlaveAddr, uint8_t *pDataOut, uint16_t Size); //接收数据
static PalI2C_HandleTypeDef hi2c1; //声明句柄使用PAL库IICint main(void)
{PAL_Init();//App_I2C_Init();hi2c1.Init.I2Cx = I2C1;hi2c1.Init.I2C_ClockSpeed = 400000;hi2c1.Init.I2C_DutyCycle = I2C_DutyCycle_2;PAL_I2C_Init(&hi2c1);const uint8_t oled_init_command[] = {0x00, // Data Stream0xa8, 0x3f, // Set MUX Ratio0xd3, 0x00, // Set Display Offset 0x40, // Set Display Start Line0xa0, // Set Segment re-map0xc0, // Set COM Output Scan Direction0xda, 0x02, // Set COM Pins hardware configuration0x81, 0x7f, // Set Contrast Control0xa5, // Enable Entire Display On0xa6, // Set Normal Display0xd5, 0x80, // Set OSC Frequency0x8d, 0x14, // Enable charge pump regulator0xaf, // Display on}; PAL_I2C_MasterTransmit(&hi2c1,0X78,oled_init_command,sizeof(oled_init_command)/sizeof(uint8_t));//App_I2C_MasterTransmit(0x78, oled_init_command, sizeof(oled_init_command)/sizeof(uint8_t));const uint8_t oled_display_off_command[] = {0x00, 0xae};const uint8_t oled_display_on_command[] = {0x00, 0xaf};uint8_t buffer[8];// 熄灭屏幕PAL_I2C_MasterTransmit(&hi2c1,0X78,oled_display_off_command,sizeof(oled_init_command)/sizeof(uint8_t));PAL_I2C_MasterReceive(&hi2c1,0X78,buffer, 1);PAL_I2C_MasterReceive(&hi2c1,0X78,buffer, 2);PAL_I2C_MasterReceive(&hi2c1,0X78,buffer, 8);App_I2C_MasterTransmit(0x78, oled_display_on_command, sizeof(oled_display_on_command)/sizeof(uint8_t));PAL_I2C_MasterReceive(&hi2c1,0X78,buffer, 1);PAL_I2C_MasterReceive(&hi2c1,0X78,buffer, 2);PAL_I2C_MasterReceive(&hi2c1,0X78,buffer, 8);while(1){}
}static void App_I2C_Init(void)
{// #1. 初始化SCL和SDA引脚RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStruct);// #2. 为I2C1开启时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, ENABLE);RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, DISABLE);// #3. 配置I2C的参数I2C_InitTypeDef I2C_InitStruct;I2C_InitStruct.I2C_ClockSpeed = 400000;I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;// I2C_InitStruct.I2C_OwnAddress1 = 0x12;// I2C_InitStruct.I2C_Ack = I2C_Ack_Disable;// I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;I2C_Init(I2C1, &I2C_InitStruct);// #4. 使能I2CI2C_Cmd(I2C1, ENABLE);
}static ErrorStatus App_I2C_MasterTransmit(uint8_t SlaveAddr, const uint8_t *pData, uint16_t Size)
{ // #1. 等待总线空闲while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) == SET);// #2. 发送起始位I2C_GenerateSTART(I2C1, ENABLE);while(I2C_GetFlagStatus(I2C1, I2C_FLAG_SB) == RESET);// #3. 发送从机地址I2C_ClearFlag(I2C1, I2C_FLAG_AF);I2C_SendData(I2C1, SlaveAddr & 0xfe);while(I2C_GetFlagStatus(I2C1, I2C_FLAG_ADDR) == RESET){if(I2C_GetFlagStatus(I2C1, I2C_FLAG_AF) == SET){goto TAG_ERROR;}}I2C_ReadRegister(I2C1, I2C_Register_SR1);I2C_ReadRegister(I2C1, I2C_Register_SR2);// #4. 发送数据uint32_t i;for(i=0;i<Size;i++){while(I2C_GetFlagStatus(I2C1, I2C_FLAG_TXE) == RESET){if(I2C_GetFlagStatus(I2C1, I2C_FLAG_AF) == SET){goto TAG_ERROR;}}I2C_SendData(I2C1, pData[i]);}while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF) == RESET){if(I2C_GetFlagStatus(I2C1, I2C_FLAG_AF) == SET){goto TAG_ERROR;}}// #5. 发送停止位I2C_GenerateSTOP(I2C1, ENABLE);return SUCCESS;TAG_ERROR:I2C_GenerateSTOP(I2C1, ENABLE);return ERROR;
}static ErrorStatus App_I2C_MasterReceive(uint8_t SlaveAddr, uint8_t *pDataOut, uint16_t Size)
{if(Size == 0){return ERROR;}// #1. 等待总线空闲while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) == SET);// #2. 发送起始位I2C_GenerateSTART(I2C1, ENABLE);while(I2C_GetFlagStatus(I2C1, I2C_FLAG_SB) == RESET); // #3. 发送从机地址I2C_ClearFlag(I2C1, I2C_FLAG_AF);I2C_SendData(I2C1, SlaveAddr | 0x01);while(I2C_GetFlagStatus(I2C1, I2C_FLAG_ADDR) == RESET){if(I2C_GetFlagStatus(I2C1, I2C_FLAG_AF) == SET){goto TAG_ERROR;}}// #4. 接收数据I2C_AcknowledgeConfig(I2C1, ENABLE);I2C_NACKPositionConfig(I2C1, I2C_NACKPosition_Current);if(Size == 1){I2C_ReadRegister(I2C1, I2C_Register_SR1);I2C_ReadRegister(I2C1, I2C_Register_SR2);I2C_AcknowledgeConfig(I2C1, DISABLE);I2C_NACKPositionConfig(I2C1, I2C_NACKPosition_Current);I2C_GenerateSTOP(I2C1, ENABLE);while(I2C_GetFlagStatus(I2C1, I2C_FLAG_RXNE)==RESET);pDataOut[0] = I2C_ReceiveData(I2C1);}else if(Size == 2){I2C_AcknowledgeConfig(I2C1, ENABLE);I2C_ReadRegister(I2C1, I2C_Register_SR1);I2C_ReadRegister(I2C1, I2C_Register_SR2);while(I2C_GetFlagStatus(I2C1, I2C_FLAG_RXNE) == RESET);I2C_AcknowledgeConfig(I2C1, DISABLE);I2C_GenerateSTOP(I2C1, ENABLE);while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF) == RESET);pDataOut[0] = I2C_ReceiveData(I2C1);pDataOut[1] = I2C_ReceiveData(I2C1);}else{uint32_t i;I2C_ReadRegister(I2C1, I2C_Register_SR1);I2C_ReadRegister(I2C1, I2C_Register_SR2);for(i=0;i<Size-3;i++){while(I2C_GetFlagStatus(I2C1, I2C_FLAG_RXNE) == RESET);pDataOut[i] = I2C_ReceiveData(I2C1);}while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF) == RESET);I2C_AcknowledgeConfig(I2C1, DISABLE);pDataOut[Size-3] = I2C_ReceiveData(I2C1);I2C_GenerateSTOP(I2C1, ENABLE);pDataOut[Size-2] = I2C_ReceiveData(I2C1);while(I2C_GetFlagStatus(I2C1, I2C_FLAG_RXNE) == RESET);pDataOut[Size-1] = I2C_ReceiveData(I2C1);}return SUCCESS;
TAG_ERROR:I2C_GenerateSTOP(I2C1, ENABLE);return ERROR;
}
这篇关于pal库 IIC的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!