pal库 IIC
2023-12-22 00:20:15
数据接收的流程
下面的流程可以用一个接口来实现 一个函数接口
第一个就是从机的地址 第二个参数就是接收数据的缓冲区 第三个参数就是 接收数据的大小
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 Stream
0xa8, 0x3f, // Set MUX Ratio
0xd3, 0x00, // Set Display Offset
0x40, // Set Display Start Line
0xa0, // Set Segment re-map
0xc0, // Set COM Output Scan Direction
0xda, 0x02, // Set COM Pins hardware configuration
0x81, 0x7f, // Set Contrast Control
0xa5, // Enable Entire Display On
0xa6, // Set Normal Display
0xd5, 0x80, // Set OSC Frequency
0x8d, 0x14, // Enable charge pump regulator
0xaf, // 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. 使能I2C
I2C_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库IIC
int 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 Stream
0xa8, 0x3f, // Set MUX Ratio
0xd3, 0x00, // Set Display Offset
0x40, // Set Display Start Line
0xa0, // Set Segment re-map
0xc0, // Set COM Output Scan Direction
0xda, 0x02, // Set COM Pins hardware configuration
0x81, 0x7f, // Set Contrast Control
0xa5, // Enable Entire Display On
0xa6, // Set Normal Display
0xd5, 0x80, // Set OSC Frequency
0x8d, 0x14, // Enable charge pump regulator
0xaf, // 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. 使能I2C
I2C_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;
}
文章来源:https://blog.csdn.net/qq_74185687/article/details/135139986
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!