KF32F350_demo-I2C读写外部eeprom
main.c/****************************************************************************************
*
* 文件名: main.c
* 项目名: EEPROM
* 版 本:V2.1
* 日 期:2019年11月16日
* 作 者:ChipON_AE/FAE_Group
*
****************************************************************************************/
#include "system_init.h"
#include "EEPROM_24LC256.h"
#include "Usart.h"
/**
* 描述GPIOx 输出初始化配置。
* 输入 : GPIOx: 指向GPIO内存结构的指针,取值为GPIOA_SFR~GPIOH_SFR。
* GpioPin: 端口引脚掩码,取值为GPIO_PIN_MASK_0~GPIO_PIN_MASK_15中的一个或多个组合。
* 返回无。
*/
void GPIOInit_Output_Config(GPIO_SFRmap* GPIOx,uint16_t GpioPin)
{
/*初始化复位GPIOx外设,使能GPIOx外设时钟*/
GPIO_Reset(GPIOx);
/* 配置 Pxy作为输出模式参数 */
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_Struct_Init(&GPIO_InitStructure);
GPIO_InitStructure.m_Pin = GpioPin;
GPIO_InitStructure.m_Speed = GPIO_LOW_SPEED; //初始化 GPIO输出速度
GPIO_InitStructure.m_Mode = GPIO_MODE_OUT; //初始化 GPIO方向为输出
GPIO_InitStructure.m_PullUp = GPIO_NOPULL; //初始化 GPIO是否上拉
GPIO_InitStructure.m_PullDown = GPIO_NOPULL; //初始化 GPIO是否下拉
GPIO_Configuration(GPIOx,&GPIO_InitStructure);
GPIO_Set_Output_Data_Bits(GPIOx,GpioPin,Bit_SET); //先设置为高电平
}
/**
* 描述I2Cx引脚上拉初始化及重映射配置。
* 输入无
*
* 返回无。
*/
void I2C_GPIO_init(void)
{
/*I2Cx引脚上拉初始化及重映射配置*/
GPIO_InitTypeDef I2C_GPIO_Init;
I2C_GPIO_Init.m_Mode = GPIO_MODE_RMP; //GPIO设为重映射
I2C_GPIO_Init.m_OpenDrain = GPIO_POD_OD; //GPIO设为开漏输出
I2C_GPIO_Init.m_Pin = GPIO_PIN_MASK_0|GPIO_PIN_MASK_1;//选用的GPIO端口
I2C_GPIO_Init.m_PullUp = GPIO_PULLUP; //GPIO设为上拉
I2C_GPIO_Init.m_PullDown = GPIO_NOPULL; //GPIO不下拉
I2C_GPIO_Init.m_Speed = GPIO_HIGH_SPEED; //GPIO速度设为高速
GPIO_Pin_RMP_Config(GPIOA_SFR,GPIO_Pin_Num_0,GPIO_RMP_AF8_I2C0);//设PA0为I2C0的SDA
GPIO_Pin_RMP_Config(GPIOA_SFR,GPIO_Pin_Num_1,GPIO_RMP_AF8_I2C0);//设PA1为I2C0的SCK
GPIO_Configuration(GPIOA_SFR,&I2C_GPIO_Init);
}
/**
* 描述初始化I2Cx参数配置波特率设置。
* 输入I2Cx:指向I2C内存结构的指针,取值为I2C0_SFR~I2C3_SFR。
*
* 返回无。
*/
void I2C_init(I2C_SFRmap* I2Cx)
{
/*I2Cx*/
I2C_Reset(I2Cx);
I2C_InitTypeDef newStruct_I2C;
newStruct_I2C.m_Mode = I2C_MODE_I2C; //I2C模式
newStruct_I2C.m_ClockSource = I2C_CLK_SCLK; //采用主频120M,一个时钟周期为0.00833us
newStruct_I2C.m_BADR10 = I2C_BUFRADDRESS_7BIT; //7位的地址模式
newStruct_I2C.m_MasterSlave = I2C_MODE_SMBUSHOST; //SMBus类型选择:HOST
newStruct_I2C.m_BaudRateL = 150; //波特率低电平时间:150X0.00833us=1.25us
newStruct_I2C.m_BaudRateH = 150; //波特率高电平时间:150X0.00833us=1.25us 得到400KHZ
newStruct_I2C.m_AckEn = TRUE; //ACK应答使能
newStruct_I2C.m_AckData = I2C_ACKDATA_ACK; //应答ACK
I2C_Configuration(I2Cx, &newStruct_I2C);
/*使能I2C模块*/
I2C_Cmd(I2Cx,TRUE);
I2C_Clear_INTERRUPT_Flag(I2Cx);//清I2C中断标志位
}
//主函数
void main()
{
/*用户可参考该例程在KF32F350_demo板上实现I2C主模式读写外部的EERPOM功能。
* 例程中使用I2C0 PA0 PA1用于主机I2C通信。EEPROM 24LC256最高支持400KHZ。
* 功能简述: KF32F350通过I2C总线以CPU读写的形式在EERPOM的0x0000地址写入64个字节数据,然后再从0x0000地址再读出64个字节数据进行对比,
* 数据匹配后PB8翻转LED0闪烁,否则PB9翻转LED1闪烁
* 硬件说明: 设PA0为I2C0的SDA设PA1为I2C0的SCK
* PB8对应控制LED0灯\PB9对应控制LED1灯\PB10对应控制LED2灯
* 如果需要用串口接USART0_RX PB6 USART0_TX0 PB7并在Usart.h打开 串口宏定义Usart_Print1
*EERPOM:型号为24LC256
*
*/
//系统时钟120M,外设高频时钟16M
SystemInit();//系统时钟初始化
/*PB9 PB9 PB10初始化设为输出高*/
GPIOInit_Output_Config(GPIOB_SFR,GPIO_PIN_MASK_8|GPIO_PIN_MASK_9|GPIO_PIN_MASK_10);
//I2C GPIO选用及功能重映射
I2C_GPIO_init(); //设PA0为I2C0的SDA设PA1为I2C0的SCK
//初始化I2C0模块参数
I2C_init(I2C0_SFR); //波特率设为400KHZ
#if Usart_Print
//配置USART0引脚重映射
GPIO_USART();////USART2_RX PB15 USART2_TX0 PB14
USART_Async_config(USART2_SFR);//全双工异步8bit 9600波特率
#endif
while(1)
{
#if Usart_Print
//串口打印读到的数组数据
USART_Send(USART2_SFR,i2c_buffer_read,sizeof(i2c_buffer_read));
#endif
if(I2C_OK == AT24LC256_TEST())//检测写入EERPOM与读出数据是否匹配
{
GPIO_Toggle_Output_Data_Config(GPIOB_SFR,GPIO_PIN_MASK_8);//PB8翻转
Delay(0XFFFFF);
}else
{
GPIO_Toggle_Output_Data_Config(GPIOB_SFR,GPIO_PIN_MASK_9);//PB9翻转
}
}
}
/**
* 描述 报告校验发生错误的文件和行
* 输入 file: 指向文件名称的指针
* line: 校验错误的行
* 返回无。
*/
void check_failed(uint8_t* file, uint32_t line)
{
/* 用户可以添加自己的代码实现报告文件名和行号,
例如: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
while(1)
{
;
}
}
EEPROM_24LC256.c
/**
********************************************************************
* 文件名EEPROM_24LC256.c
* 作者 ChipON_AE/FAE_Group
* 版本V2.1
* 日期2019-11-16
* 描述该文件提供了EERPOM读写功能函数等相关函数。
*
*********************************************************************
*/
#include "system_init.h"
#include "EEPROM_24LC256.h"
#include "Usart.h"
I2C_SFRmap* I2C_Choose;
//延时函数 局部变量用volatile声明,否则可能会被优化
void Delay(volatile uint32_t cnt)
{
while(cnt--);
}
/**
* 描述eeprom 写入单字节数据。
* 输入write_address:eeprom 16位寄存器地址
* p_buffer: 写入数据,取值为10位数据。
* 返回无。
*/
void eeprom_byte_write(uint16_t write_address,uint32_t p_buffer)
{
I2C_Choose=I2C0_SFR;//选择I2C0_SFR I2C1_SFR I2C2_SFR I2C3_SFR
static uint8_t EEPROM_AddH=0;
static uint8_t EEPROM_AddL=0;
EEPROM_AddL=write_address& 0xff; //低8位寄存器地址
EEPROM_AddH=(write_address>>8)& 0xff; //高8位寄存器地址
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
I2C_Cmd(I2C_Choose,TRUE); //使能I2C模块
/*起始位*/
I2C_Generate_START(I2C_Choose,TRUE); //使能起始信号
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待起始位稳定
/*发送I2C从机地址*/
I2C_SendData(I2C_Choose,EEPROM_I2C_ADDRESS); //发送从机I2C地址
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待发送完成
/*发送高位地址*/
I2C_SendData(I2C_Choose,EEPROM_AddH); //发送从机高位寄存器地址
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待发送完成
/*发送低位地址*/
I2C_SendData(I2C_Choose,EEPROM_AddL); //发送从机低位寄存器地址
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待发送完成
/*发送数据*/
I2C_SendData(I2C_Choose, p_buffer); //发送8位数据
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待发送完成
/*停止位*/
I2C_Generate_STOP(I2C_Choose,TRUE); //使能停止信号
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待停止完成
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
I2C_Clear_Stop_Flag(I2C_Choose); //清I2C停止标志位PIF位
I2C_Cmd(I2C_Choose,FALSE); //关闭I2C模块
}
/**
* 描述eeprom 写入多字节数据。
* 输入write_address:eeprom 16位寄存器地址
* p_buffer: 写入数据指针
* number_of_byte:写入数据长度
* 返回无。
*/
void eeprom_buffer_write(uint16_t Write_address,uint8_t *p_buffer,uint16_t number_of_byte)
{
I2C_Choose=I2C0_SFR;//选择I2C0_SFR I2C1_SFR I2C2_SFR I2C3_SFR
staticuint8_t EEPROM_AddH=0;
staticuint8_t EEPROM_AddL=0;
EEPROM_AddL=Write_address& 0xff; //低8位寄存器地址
EEPROM_AddH=(Write_address>>8)& 0xff; //高8位寄存器地址
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
I2C_Cmd(I2C_Choose,TRUE); //使能I2C模块
/*起始位*/
I2C_Generate_START(I2C_Choose,TRUE); //使能起始信号
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose));
/*发送I2C从机地址*/
I2C_SendData8(I2C_Choose,EEPROM_I2C_ADDRESS); //发送从机I2C地址
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待发送完成
while(I2C_Get_Ack_Fail_Flag(I2C_Choose)); //判断是否有ACK应答,如没有则停止,如果有则继续发
/*发送高位地址*/
I2C_SendData8(I2C_Choose,EEPROM_AddH); //发送从机高位寄存器地址
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待发送完成
/*发送低位地址*/
I2C_SendData8(I2C_Choose,EEPROM_AddL); //发送从机低位寄存器地址
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待发送完成
/* 循环写数据操作 */
while(number_of_byte--){
I2C_SendData8(I2C_Choose, *p_buffer); //发送8位数据
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
/* 指向下一个所要写的字节 */
p_buffer++;
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待发送完成
}
/*停止位*/
I2C_Generate_STOP(I2C_Choose,TRUE); //使能停止信号
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待停止完成
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
I2C_Clear_Stop_Flag(I2C_Choose); //清I2C停止标志位PIF位
I2C_Cmd(I2C_Choose,FALSE); //关闭I2C模组
}
/**
* 描述eeprom 读出单字节数据。
* 输入write_address:eeprom 16位寄存器地址
* p_buffer: 读出数据,取值为8位数据。
* 返回无。
*/
void eeprom_byte_read(uint16_t Write_address,uint8_t p_buffer)
{
I2C_Choose=I2C0_SFR;//选择I2C0_SFR I2C1_SFR I2C2_SFR I2C3_SFR
static uint8_t EEPROM_AddH=0;
static uint8_t EEPROM_AddL=0;
EEPROM_AddL=Write_address& 0xff;//低8位寄存器地址
EEPROM_AddH=(Write_address>>8)& 0xff;//高8位寄存器地址
I2C_Cmd(I2C_Choose,TRUE);
/*起始位*/
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
I2C_Generate_START(I2C_Choose,TRUE); //使能起始信号
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待起始位稳定
/*发送I2C从机地址*/
I2C_SendData8(I2C_Choose,EEPROM_I2C_ADDRESS); //发送从机I2C地址
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待发送完成
while(I2C_Get_Ack_Fail_Flag(I2C_Choose)); //判断是否有ACK应答,如没有则停止,如果有则继续发
/*发送要读寄存器高位地址*/
I2C_SendData8(I2C_Choose,EEPROM_AddH); //发送从机高位寄存器地址
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待发送完成
/*发送要读寄存器低位地址*/
I2C_SendData8(I2C_Choose,EEPROM_AddL); //发送从机低位寄存器地址
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待发送完成
I2C_Cmd(I2C_Choose,FALSE); //关I2C模块
I2C_Clear_Start_Flag(I2C_Choose); //清I2C起始标志位SIF位
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
I2C_Cmd(I2C_Choose,TRUE); //使能I2C模块
/*起始位*/
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF
I2C_Generate_START(I2C_Choose,TRUE); //使能起始信号
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待起始信号稳定
/*发送读指令*/
I2C_SendData8(I2C_Choose,EEPROM_I2C_ADDRESS|0x01);//发送从机地址及读操作
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清标志位ISIF位
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待发送完成ISIF会置1
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //然后完成清标志位ISIF位
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose));//等待读取Buff完成ISIF会置1
if(I2C_Get_Receive_Buff_Flag(I2C_Choose)) //判断Buff是否为满
{
I2C_Ack_DATA_Config(I2C_Choose,I2C_ACKDATA_ACK);//回复ACK
p_buffer = I2C_ReceiveData(I2C_Choose);
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //然后读完后清标志位ISIF位
}
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose));
/*停止位*/
I2C_Generate_STOP(I2C_Choose,TRUE); //使能停止信号
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待停止完成
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
I2C_Clear_Stop_Flag(I2C_Choose); //清I2C停止标志位PIF位
I2C_Cmd(I2C_Choose,FALSE); //关闭I2C模组
}
/**
* 描述eeprom 读出多字节数据。
* 输入write_address:eeprom 16位寄存器地址
* p_buffer: 读出数据指针
* number_of_byte:读出数据长度
* 返回无。
*/
void eeprom_buffer_read(uint16_t Write_address,uint8_t *p_buffer,uint16_t number_of_byte)
{
I2C_Choose=I2C0_SFR;//选择I2C0_SFR I2C1_SFR I2C2_SFR I2C3_SFR
static uint8_t EEPROM_AddH=0;
static uint8_t EEPROM_AddL=0;
EEPROM_AddL=Write_address& 0xff; //低8位寄存器地址
EEPROM_AddH=(Write_address>>8)& 0xff;//高8位寄存器地址
I2C_Cmd(I2C_Choose,TRUE); //使能I2C3模块
/*起始位*/
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
I2C_Generate_START(I2C_Choose,TRUE); //使能起始信号
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待起始位稳定
/*发送I2C从机地址*/
I2C_SendData8(I2C_Choose,EEPROM_I2C_ADDRESS); //发送从机I2C地址
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待发送完成
while(I2C_Get_Ack_Fail_Flag(I2C_Choose)); //判断是否有ACK应答,如没有则停止,如果有则继续发
/*发送要读寄存器高位地址*/
I2C_SendData8(I2C_Choose,EEPROM_AddH); //发送从机高位寄存器地址
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待发送完成
/*发送要读寄存器低位地址*/
I2C_SendData8(I2C_Choose,EEPROM_AddL); //发送从机低位寄存器地址
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待发送完成
I2C_Cmd(I2C_Choose,FALSE); //关I2C模块
I2C_Clear_Start_Flag(I2C_Choose); //清I2C起始标志位SIF位
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清标志位ISIF位
I2C_Cmd(I2C_Choose,TRUE); //打开I2C模块
/*起始位*/
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清中断标志位ISIF位
I2C_Generate_START(I2C_Choose,TRUE); //起始信号
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待起始位稳定
/*发送读指令*/
I2C_SendData8(I2C_Choose,EEPROM_I2C_ADDRESS|0x01);//发送从机地址及读操作
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清标志位ISIF位
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待发送完成ISIF会置1
while(I2C_Get_Ack_Fail_Flag(I2C_Choose)); //判断是否有ACK应答,如没有则停止,如果有则继续发
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //然后完成清标志位ISIF位
while(number_of_byte)
{
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose));//等待读取Buff完成ISIF会置1
if(I2C_Get_Receive_Buff_Flag(I2C_Choose)) //判断Buff是否为满
{
*p_buffer = I2C_ReceiveData(I2C_Choose);
I2C_Ack_DATA_Config(I2C_Choose,I2C_ACKDATA_ACK);//回复ACK
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //然后读完后清标志位ISIF位
p_buffer++; /* 指向下一个被读取的字节将被保存的位置 */
/* 递减读取字节计数器 */
number_of_byte--;
}
}
/*停止位*/
I2C_Generate_STOP(I2C_Choose,TRUE); //使能停止信号
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
while(!I2C_Get_INTERRUPT_Flag(I2C_Choose)); //等待停止完成
I2C_Clear_INTERRUPT_Flag(I2C_Choose); //清I2C中断标志位ISIF位
I2C_Clear_Stop_Flag(I2C_Choose); //清I2C停止标志位PIF位
I2C_Cmd(I2C_Choose,FALSE); //关闭I2C模组
}
/**
* 描述先写64个字节数据并读出64个字节数据进行比较。
* 输入无
* 返回 1 :数据对比匹配。
* 0 :数据对比不匹配。
*/
uint8_t AT24LC256_TEST(void)
{
static volatile uint16_t i;
static volatile uint16_t j;
i=0;
j=0;
/* 初始化i2c写缓冲区 */
for(i = 0;i < BUFFER_SIZE;i++)
{
i2c_buffer_write=i;
}
Delay(0XFFFF);
Delay(0XFFFF);
Delay(0XFFFF);
/* EEPROM 数据写入 */
eeprom_buffer_write(EEP_FIRST_PAGE,i2c_buffer_write,sizeof(i2c_buffer_write));
Delay(0XFFFF);
Delay(0XFFFF);
Delay(0XFFFF);
Delay(0XFFFF);
Delay(0XFFFF);
/* EEPROM 数据读取 */
eeprom_buffer_read(EEP_FIRST_PAGE,i2c_buffer_read,sizeof(i2c_buffer_read));
Delay(0XFFFF);
Delay(0XFFFF);
Delay(0XFFFF);
Delay(0XFFFF);
Delay(0XFFFF);
for(j = 0;j < BUFFER_SIZE;j++)
{
if(i2c_buffer_read != i2c_buffer_write)
{
return I2C_FAIL;
}
}
return I2C_OK;
}
system_init.c
/**
******************************************************************************
* 文件名system_init.c
* 作者ChipON_AE/FAE_Group
* 版本V2.1
* 日期2019-11-16
* 描述该文件提供了外设时钟与系统时钟初始化
*
******************************************************************************
*/
#include "system_init.h"
/**
* 描述时钟默认配置。
* 输入无。
* 返回无。
*/
static void SetSysClock(void)
{
/* 使能内部高频时钟*/
OSC_INTHF_Software_Enable(TRUE);
while(OSC_Get_INTHF_INT_Flag() != SET);
/* PLL时钟源选择 */
#ifdef SYSCLK_FREQ_HSI
OSC_PLL_Input_Source_Config(PLL_INPUT_INTHF);
#else
OSC_PLL_Input_Source_Config(PLL_INPUT_EXTHF);
#endif
/* PLL倍频时钟选择 */
#ifdef SYSCLK_FREQ_48MHz
OSC_PLL_Multiple_Value_Select(48,2,8);
#elif defined SYSCLK_FREQ_72MHz
OSC_PLL_Multiple_Value_Select(36,2,4);
#elif defined SYSCLK_FREQ_96MHz
OSC_PLL_Multiple_Value_Select(12,1,2);
#elif defined SYSCLK_FREQ_120MHz
OSC_PLL_Multiple_Value_Select(30,2,2);
#endif
OSC_PLL_Start_Delay_Config(PLL_START_DELAY_1024);
OSC_PLL_Software_Enable(TRUE);
OSC_PLL_RST();
while(OSC_Get_PLL_INT_Flag() != SET);
/* 主时钟配置 */
OSC_SCK_Division_Config(SCLK_DIVISION_1);
OSC_SCK_Source_Config(SCLK_SOURCE_PLL);
/* 外设高速时钟 */
OSC_HFCK_Division_Config(HFCK_DIVISION_1);
OSC_HFCK_Source_Config(HFCK_SOURCE_INTHF);
OSC_HFCK_Enable(TRUE);
OSC_LFCK_Division_Config(LFCK_DIVISION_1); //低频工作分频选择
OSC_LFCK_Source_Config (LFCK_INPUT_INTLF); //选择INTLF作为LFCLK时钟
OSC_LFCK_Enable (TRUE); //LFCLK时钟信号允许
OSC_INTLF_Software_Enable(TRUE);
OSC_INTHF_Software_Enable(TRUE); //内部高频振荡器软件使能
}
/**
* 描述系统初始化。
* 输入无。
* 返回无。
*/
void SystemInit(void)
{
/* 时钟配置 */
SetSysClock();
}
Usart.c
/**
********************************************************************
* 文件名Usart.c
* 作者 ChipON_AE/FAE_Group
* 版本V2.1
* 日期2019-11-16
* 描述该文件提供了Usart GPIO初始化、Usart配置参数、Usart发送函数等相关函数。
*
*********************************************************************
*/
#include "system_init.h"
/**
* 描述 串口GPIO重映射
* 输入 无
* 返回 无
*/
void GPIO_USART(void)
{
/* 端口重映射AF5 */
//USART2_RX PB15
//USART2_TX0 PB14
GPIO_Write_Mode_Bits(GPIOB_SFR ,GPIO_PIN_MASK_14, GPIO_MODE_RMP); //重映射IO口功能模式
GPIO_Write_Mode_Bits(GPIOB_SFR ,GPIO_PIN_MASK_15, GPIO_MODE_RMP); //重映射IO口功能模式
GPIO_Pin_RMP_Config (GPIOB_SFR, GPIO_Pin_Num_14, GPIO_RMP_AF5_USART2); //重映射为USART2
GPIO_Pin_RMP_Config (GPIOB_SFR,GPIO_Pin_Num_15, GPIO_RMP_AF5_USART2); //重映射为USART2
GPIO_Pin_Lock_Config (GPIOB_SFR ,GPIO_PIN_MASK_14, TRUE); //配置锁存
GPIO_Pin_Lock_Config (GPIOB_SFR ,GPIO_PIN_MASK_15, TRUE); //配置锁存
}
/**
* 描述 串口发送
* 输入 USARTx: 指向USART内存结构的指针,取值为USART0_SFR~USART8_SFR
* Databuf: 指向发送数据的指针
* length: 发送的长度
* 返回 无
*/
void USART_Send(USART_SFRmap* USARTx, uint8_t* Databuf, uint32_t length)
{
uint32_t i;
for(i=0;i<length;i++)
{
//串口发送
USART_SendData(USARTx,Databuf);
//发送完成标志
while(!USART_Get_Transmitter_Empty_Flag(USARTx));
}
}
/**
* 描述串口异步全双工配置(默认8bit收发使能全双工 9600)
* 输入 指向USART内存结构的指针,取值为USART0_SFR~USART8_SFR
* 返回 无
*/
void USART_Async_config(USART_SFRmap *USARTx)
{
USART_InitTypeDef USART_InitStructure;
USART_Struct_Init(&USART_InitStructure);
USART_InitStructure.m_Mode=USART_MODE_FULLDUPLEXASY; //全双工
USART_InitStructure.m_TransferDir=USART_DIRECTION_FULL_DUPLEX; //传输方向
USART_InitStructure.m_WordLength=USART_WORDLENGTH_8B; //8位数据
USART_InitStructure.m_StopBits=USART_STOPBITS_1; //1位停止位
USART_InitStructure.m_BaudRateBRCKS=USART_CLK_HFCLK; //内部高频时钟作为 USART波特率发生器时钟
/* 波特率 =Fck/(16*z(1+x/y)) 外设时钟内部高频16M*/
//4800 z:208 x:0 y:0
//9600 z:104 x:0 y:0
//19200 z:52 x:0 y:0
//115200z:8 x:1 y:13
//波特率9600
USART_InitStructure.m_BaudRateInteger=104; //USART波特率整数部分z,取值为0~65535
USART_InitStructure.m_BaudRateNumerator=0; //USART波特率小数分子部分x,取值为0~0xF
USART_InitStructure.m_BaudRateDenominator=0; //USART波特率小数分母部分y,取值为0~0xF
USART_Reset(USARTx); //USARTx复位
USART_Configuration(USARTx,&USART_InitStructure); //USARTx配置
USART_Clear_Transmit_BUFR_INT_Flag(USARTx); //USARTx发送BUF清零
USART_RESHD_Enable (USARTx, TRUE); //使能RESHD位
USART_Cmd(USARTx,TRUE); //USARTx使能
}
有没有整个工程的文件,感谢,感谢楼主分享。
希望楼主上传一下整个工程的文件,我想看看里面的工程是如何配置的,我的配置好像有点问题,不能够运行的。
代码很规范,学习学习 写的可读性还蛮高的 楼主应该写码习惯很好 感谢楼主分享 还是要好好的学习一下的。 硬件收发器的学会了,很有用的。 只看函数和寄存器的话,确实和ARM系列没什么区别,希望自己架构的芯片越来越好
页:
[1]