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
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。