【国民技术N32G430】06 综合调试,RTC,模拟IIC,串口
[复制链接]
本帖最后由 秦天qintian0303 于 2022-10-25 10:58 编辑
前言:
疫情真是一个烦人的事情,所有的计划都被无情的打断,转瞬就要到测评结束的时候了,得快马加鞭,于是就把实时时钟/传感器数据采集/串口部分都统一到这一篇章进行介绍。
准备工作:
在此期间也是把N32G430的转接板做了回来,之前准备就用杜邦线连接进行测试着,不过发现使用杜邦线连接有几个弊端:
一个是咱们的EVA板不好固定;
还有就是移动过程中会出现接触不良的现象。
所以还是做了转接板,由于手工测量的原因(N32G430C8L7_STB_V1.0.pcb并没有内容),实物还是存在一些偏差,简单调整了引脚角度还是可以装上的。
粗略尺寸图如下:
组装后实物图如下:
引脚目前看没有什么问题,之前写的程序可以正常运行,且外设驱动正常。
接下来就是N32G430测评页面操作分析:
依次思维脑图进行进行一个整体测试系统的构造。
具体测试:
接下来就进行剩余三个部分的具体测试内容。
一、RTC测试体验
RTC的主要部分主要分开机检测、初始化、和RTC的获取和设置。
每次开机通过备份寄存器存储的数据进行判断RTC是否在工作,备份寄存器是通过电池供电引脚供电,所以不会因为MCU的供电变化而停止工作,若是备份寄存器复位了就需要进行RTC的初始化了。
代码如下:
void port_RTC_init(void)
{
/* Enable the PWR clock */
RCC_APB1_Peripheral_Clock_Enable(RCC_APB1_PERIPH_PWR);
/* Allow access to RTC */
PWR_RTC_Backup_Access_Enable();
/* check data from bpr dt register */
if(RTC_Backup_Register_Read(RTC_BACKUP_REGISTER_1) != ERTC_BPR_DT1)
{
/* ertc configuration */
ertc_config();
/* write to ertc bpr data registers */
RTC_Backup_Register_Write(RTC_BACKUP_REGISTER_1,ERTC_BPR_DT1);
}
}
初始化代码:
/******************************************************************************/
//******************************************************************************
// 函数名称 : RTC_Date_And_Time_Default_Value
// 函数描述 : 时间参数初始值
// 输入参数 :
// 参数描述 : 无
// 输出参数 : 无
// 返回值 : 无
//******************************************************************************
void RTC_Date_And_Time_Default_Value(void)
{
eRTC_set.week = 2;
eRTC_set.day = 20;
eRTC_set.month = 9;
eRTC_set.year = 22;
eRTC_set.hour = 10;
eRTC_set.min = 0;
eRTC_set.sec = 0;
}
/**
*\*\name RTC_CLKSource_Config.
*\*\fun Configure the RTC peripheral by selecting the clock source.
*\*\param ClkSrc
*\*\ - RTC_CLK_HSE128 clock source select HSE/128
*\*\ - RTC_CLK_LSE clock source select LSE
*\*\ - RTC_CLK_LSI clock source select LSI
*\*\param FirstLastCfg
*\*\ - RTC_CLK_FIRST_CONFIG
*\*\ - RTC_CLK_LAST_CONFIG
*\*\return none
**/
//******************************************************************************
// 函数名称 : RTC_CLKSource_Config
// 函数描述 : RTC时钟配置,并获取分频参数
// 输入参数 :
// ClkSrc:
// - RTC_CLK_HSE128 clock source select HSE/128
// - RTC_CLK_LSE clock source select LSE
// - RTC_CLK_LSI clock source select LSI
//param FirstLastCfg:
// - RTC_CLK_FIRST_CONFIG
// - RTC_CLK_LAST_CONFIG
// 参数描述 : 无
// 输出参数 : 无
// 返回值 : 无
//******************************************************************************
void RTC_CLKSource_Config(uint8_t ClkSrc, uint8_t FirstLastCfg)
{
/* Enable the PWR clock */
RCC_APB1_Peripheral_Clock_Enable(RCC_APB1_PERIPH_PWR);
RCC_APB2_Peripheral_Clock_Enable(RCC_APB2_PERIPH_AFIO);
/* Allow access to RTC */
PWR_RTC_Backup_Access_Enable();
RCC_Backup_Reset();
/* Disable RTC clock */
RCC_RTC_Clock_Disable();
if (ClkSrc == RTC_CLK_HSE128)
{
if (FirstLastCfg == RTC_CLK_FIRST_CONFIG)
{
/* Enable HSE */
RCC_LSI_Disable();
RCC_HSE_Config(RCC_HSE_ENABLE);
while (RCC_HSE_Stable_Wait() == ERROR)
{
}
RCC_RTC_Clock_Config(RCC_RTCCLK_SRC_HSE_DIV128);
}
else
{
RCC_LSI_Disable();
RCC_RTC_Clock_Config(RCC_RTCCLK_SRC_HSE_DIV128);
/* Enable HSE */
RCC_HSE_Config(RCC_HSE_ENABLE);
while (RCC_HSE_Stable_Wait() == ERROR)
{
}
}
SynchPrediv = 0x1E8; // 8M/128 = 62.5KHz
AsynchPrediv = 0x7F; // value range: 0-7F
}
else if (ClkSrc == RTC_CLK_LSE)
{
if (FirstLastCfg == RTC_CLK_FIRST_CONFIG)
{
/* Enable the LSE OSC32_IN PC14 */
RCC_LSI_Disable(); // LSI is turned off here to ensure that only one clock is turned on
#if (_LSE_BYPASS_)
RCC_LSE_Config(RCC_LSE_BYPASS, 0x141);
#else
RCC_LSE_Config(RCC_LSE_ENABLE, 0x141);
#endif
while (RCC_Flag_Status_Get(RCC_FLAG_LSERD) == RESET)
{
}
RCC_RTC_Clock_Config(RCC_RTCCLK_SRC_LSE);
}
else
{
/* Enable the LSE OSC32_IN PC14 */
RCC_LSI_Disable();
RCC_RTC_Clock_Config(RCC_RTCCLK_SRC_LSE);
#if (_LSE_BYPASS_)
RCC_LSE_Config(RCC_LSE_BYPASS, 0x141);
#else
RCC_LSE_Config(RCC_LSE_ENABLE, 0x141);
#endif
while (RCC_Flag_Status_Get(RCC_FLAG_LSERD) == RESET)
{
}
}
SynchPrediv = 0xFF; // 32.768KHz
AsynchPrediv = 0x7F; // value range: 0-7F
}
else if (ClkSrc == RTC_CLK_LSI)
{
if (FirstLastCfg == RTC_CLK_FIRST_CONFIG)
{
/* Enable the LSI OSC */
RCC_LSI_Enable();
while (RCC_Flag_Status_Get(RCC_FLAG_LSIRD) == RESET)
{
}
RCC_RTC_Clock_Config(RCC_RTCCLK_SRC_LSI);
}
else
{
RCC_RTC_Clock_Config(RCC_RTCCLK_SRC_LSI);
/* Enable the LSI OSC */
RCC_LSI_Enable();
while (RCC_Flag_Status_Get(RCC_FLAG_LSIRD) == RESET)
{
}
}
SynchPrediv = 0x13B; // 39.64928KHz
AsynchPrediv = 0x7F; // value range: 0-7F
}
else
{
}
/* Enable the RTC Clock */
RCC_RTC_Clock_Enable();
RTC_Wait_For_Synchronization();
}
/**
*\*\name RTC_Prescaler_Config.
*\*\fun RTC prescaler config.
*\*\param RTC_InitStruct: pointer to a RTC_InitType structure.
*\*\ - RTC_HourFormat
*\*\ - RTC_24HOUR_FORMAT
*\*\ - RTC_12HOUR_FORMAT
*\*\ - RTC_AsynchPrediv the value in the 0-0x7F range
*\*\ - RTC_SynchPrediv the value in the 0-0x7FFF range
*\*\return none
**/
static void RTC_Prescaler_Config(RTC_InitType *RTC_InitStruct)
{
/* Configure the RTC data register and RTC prescaler */
RTC_InitStruct->RTC_AsynchPrediv = AsynchPrediv;
RTC_InitStruct->RTC_SynchPrediv = SynchPrediv;
RTC_InitStruct->RTC_HourFormat = RTC_24HOUR_FORMAT;
}
//******************************************************************************
// 函数名称 : ertc_config
// 函数描述 : ert初始化配置
// 输入参数 :
// 参数描述 : 无
// 输出参数 : 无
// 返回值 : 无
//******************************************************************************
void ertc_config(void)
{
RTC_Date_And_Time_Default_Value();
RTC_CLKSource_Config(RTC_CLK_LSE,RTC_CLK_FIRST_CONFIG);
RTC_Prescaler_Config(&RTC_InitStructure);
/* RTC calendar regulate */
Set_Time();
}
//******************************************************************************
// 函数名称 : Set_Time
// 函数描述 : 设置时间
// 输入参数 :
// 参数描述 : 无
// 输出参数 : 无
// 返回值 : 无
//******************************************************************************
void Set_Time(void)
{
// Date
eDRTC_set.WeekDay = eRTC_set.week;
eDRTC_set.Date = eRTC_set.day;
eDRTC_set.Month = eRTC_set.month;
eDRTC_set.Year = eRTC_set.year;
// Time
eTRTC_set.H12 = RTC_AM_H12;
eTRTC_set.Hours = eRTC_set.hour;
eTRTC_set.Minutes = eRTC_set.min;
eTRTC_set.Seconds = eRTC_set.sec;
RTC_CLKSource_Config(RTC_CLK_LSE,RTC_CLK_FIRST_CONFIG);
RTC_Write_Protection_Disable();
RTC_Prescaler_Config(&RTC_InitStructure);
RTC_Calendar_Initializes(RTC_FORMAT_BIN,&RTC_InitStructure,&eDRTC_set,&eTRTC_set,DISABLE);
RTC_Write_Protection_Enable();
}
RTC获取和设置代码:
//******************************************************************************
// 函数名称 : Get_Time
// 函数描述 : 获取时间
// 输入参数 :
// 参数描述 : 无
// 输出参数 : 无
// 返回值 : 无
//******************************************************************************
void Get_Time(void)
{
RTC_Time_Get(RTC_FORMAT_BIN,&eTRTC);
RTC_Date_Get(RTC_FORMAT_BIN,&eDRTC);
eRTC.week = eDRTC.WeekDay;
eRTC.day = eDRTC.Date;
eRTC.month = eDRTC.Month;
eRTC.year = eDRTC.Year;
eRTC.hour = eTRTC.Hours;
eRTC.min = eTRTC.Minutes;
eRTC.sec = eTRTC.Seconds;
}
这里需要注意,正常我们去除写保护就可以进行RTC寄存器的写操作了,不过N32G430还需要重新配置才能正常写,要不然就会出现RTC的随机数问题,有可能关闭写保护的操作会导致RTC复位?
二、IIC获取AHT20和SPL06数据
AHT20是一个温湿度传感器,SPL06是一个温度、大气压力传感器,两者的IIC存在一点不同,就是AHT20发送完设备地址后不用再发送寄存器地址,而SPL06的寄存器比较多,需要对特定寄存器进行访问。
软件IIC各阶段代码:
#define IIC1_RCU_GPIO_clock RCC_AHB_Peripheral_Clock_Enable(IIC1_MASTER_PERIPH_GPIO);
#define IIC1_SDA_INITOut IIC1_SDA_GPIO_OutConfig()
#define IIC1_SDA_INITIn IIC1_SDA_GPIO_InConfig()
#define IIC1_SDA_SET GPIO_Pins_Set(IIC1_MASTER_GPIO,IIC1_MASTER_SDA_PIN)
#define IIC1_SDA_RESET GPIO_Pins_Reset(IIC1_MASTER_GPIO,IIC1_MASTER_SDA_PIN)
#define IIC1_ReadSDA GPIO_Input_Pin_Data_Get(IIC1_MASTER_GPIO, IIC1_MASTER_SDA_PIN)
#define IIC1_SCL_INITOut IIC1_SCL_GPIO_OutConfig()
#define IIC1_SCL_SET GPIO_Pins_Set(IIC1_MASTER_GPIO,IIC1_MASTER_CLK_PIN)
#define IIC1_SCL_RESET GPIO_Pins_Reset(IIC1_MASTER_GPIO,IIC1_MASTER_CLK_PIN)
/*********************************全局变量**************************************/
/*********************************函数******************************************/
void IIC1_IOInit(void);
void IIC1_SDA_GPIO_OutConfig(void);
void IIC1_SDA_GPIO_InConfig(void);
void IIC1_SCL_GPIO_OutConfig(void);
void IIC1_IIC_Init(void);
void IIC1_IIC_Start(void);
void IIC1_IIC_Stop(void);
void IIC1_SendACK(uint8_t ack);
uint8_t IIC1_RecvACK(void);
uint8_t IIC1_SendByte(uint8_t dat);
uint8_t IIC1_RecvByte(void);
void IIC1_SendBytes(uint8_t len,uint8_t* dat,uint8_t dev_addr);
void IIC1_RecvBytes(uint8_t len,uint8_t* dat,uint8_t dev_addr);
void IIC1_US_SendBytes(uint8_t len,uint8_t* dat,uint8_t dev_addr,uint8_t reg_addr);
void IIC1_US_RecvBytes(uint8_t len,uint8_t* dat,uint8_t dev_addr,uint8_t reg_addr);
//******************************************************************************
//* 函数名称 : SPI_IOInit()
//* 函数描述 : SPI对应的IO口初始化
//* 输入参数 :
//* 参数描述 :
//* 输出参数 : 无
//* 返回值 : 无
//******************************************************************************
void IIC1_IOInit(void)
{
GPIO_InitType GPIO_InitStructure;
IIC1_RCU_GPIO_clock;
GPIO_Structure_Initialize(&GPIO_InitStructure);
GPIO_InitStructure.Pin = IIC1_MASTER_SDA_PIN|IIC1_MASTER_CLK_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUT_PP;
GPIO_InitStructure.GPIO_Pull = GPIO_PULL_UP;
GPIO_Peripheral_Initialize(IIC1_MASTER_GPIO, &GPIO_InitStructure);
IIC1_SDA_SET;
IIC1_SCL_SET;
}
//******************************************************************************
//* 函数名称 : IIC1_SDA_GPIO_OutConfig()
//* 函数描述 : IIC1SDA对应的IO口设置为输出模式
//* 输入参数 :
//* 参数描述 :
//* 输出参数 : 无
//* 返回值 : 无
//******************************************************************************
void IIC1_SDA_GPIO_OutConfig(void)
{
GPIO_InitType GPIO_InitStructure;
IIC1_RCU_GPIO_clock;
GPIO_Structure_Initialize(&GPIO_InitStructure);
GPIO_InitStructure.Pin = IIC1_MASTER_SDA_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUT_PP;
GPIO_InitStructure.GPIO_Pull = GPIO_PULL_UP;
GPIO_Peripheral_Initialize(IIC1_MASTER_GPIO, &GPIO_InitStructure);
}
//******************************************************************************
//* 函数名称 : IIC1_SDA_GPIO_InConfig()
//* 函数描述 : IIC1 SDA对应的IO口设置为输入模式
//* 输入参数 :
//* 参数描述 :
//* 输出参数 : 无
//* 返回值 : 无
//******************************************************************************
void IIC1_SDA_GPIO_InConfig(void)
{
GPIO_InitType GPIO_InitStructure;
IIC1_RCU_GPIO_clock;
GPIO_Structure_Initialize(&GPIO_InitStructure);
GPIO_InitStructure.Pin = IIC1_MASTER_SDA_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_INPUT;
GPIO_InitStructure.GPIO_Pull = GPIO_PULL_UP;
GPIO_Peripheral_Initialize(IIC1_MASTER_GPIO, &GPIO_InitStructure);
}
//******************************************************************************
//* 函数名称 : IIC1_SCL_GPIO_OutConfig()
//* 函数描述 : IIC1SCL对应的IO口设置为输出模式
//* 输入参数 :
//* 参数描述 :
//* 输出参数 : 无
//* 返回值 : 无
//******************************************************************************
void IIC1_SCL_GPIO_OutConfig(void)
{
GPIO_InitType GPIO_InitStructure;
IIC1_RCU_GPIO_clock;
GPIO_Structure_Initialize(&GPIO_InitStructure);
GPIO_InitStructure.Pin = IIC1_MASTER_CLK_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_INPUT;
GPIO_InitStructure.GPIO_Pull = GPIO_PULL_UP;
GPIO_Peripheral_Initialize(IIC1_MASTER_GPIO, &GPIO_InitStructure);
}
//******************************************************************************
//* 函数名称 : IIC1_IIC_Init()
//* 函数描述 : IIC初始化
//* 输入参数 :
//* 参数描述 :
//* 输出参数 : 无
//* 返回值 : 无
//******************************************************************************
void IIC1_IIC_Init(void)
{
IIC1_SDA_INITOut;
// IIC1_IIC_Stop();
IIC1_SDA_RESET;
IIC1_SCL_RESET;
}
//******************************************************************************
//* 函数名称 : IIC1_IIC_Start()
//* 函数描述 : I2C1开始信号
//* 输入参数 :
//* 参数描述 :
//* 输出参数 : 无
//* 返回值 : 无
//******************************************************************************
void IIC1_IIC_Start(void)
{
IIC1_SDA_SET;
delay_us(8);
IIC1_SCL_SET;
delay_us(14);
IIC1_SDA_RESET;
delay_us(14);
IIC1_SCL_RESET;
delay_us(14);
}
//******************************************************************************
//* 函数名称 : IIC1_IIC_Stop(void)
//* 函数描述 : IIC停止信号
//* 输入参数 :
//* 参数描述 :
//* 输出参数 : 无
//* 返回值 : 无
//******************************************************************************
void IIC1_IIC_Stop(void)
{
IIC1_SDA_RESET;
delay_us(14);
IIC1_SCL_SET;
delay_us(8);
IIC1_SDA_SET;
delay_us(14);
}
//******************************************************************************
//* 函数名称 : IIC1_SendACK(uint8_t ack)
//* 函数描述 : 发送应答信号
//* 输入参数 :ack (0:ACK 1:NAK)
//* 参数描述 :
//* 输出参数 : 无
//* 返回值 : 无
//******************************************************************************
void IIC1_SendACK(uint8_t ack)
{
IIC1_SDA_INITOut;
if(ack == 0)
IIC1_SDA_RESET; //写应答信号
else
IIC1_SDA_SET;
delay_us(14);
IIC1_SCL_SET; //拉高时钟线
delay_us(14); //延时
IIC1_SCL_RESET; //拉低时钟线
delay_us(14); //延时
}
//******************************************************************************
//* 函数名称 : uint8_t IIC1_RecvACK(void)
//* 函数描述 : 接收应答信号
//* 输入参数 :
//* 参数描述 :
//* 输出参数 : RecvACK
//* 返回值 : 无
//******************************************************************************
uint8_t IIC1_RecvACK(void)
{
uint8_t RecvACK;
IIC1_SDA_INITIn; //SDA接口为输入
delay_us(8);
IIC1_SCL_SET; //拉高时钟线
delay_us(8); //延时
RecvACK = IIC1_ReadSDA; //读应答信号
IIC1_SCL_RESET; //拉低时钟线
delay_us(8); //延时
IIC1_SDA_INITOut;
return RecvACK;
}
//******************************************************************************
//* 函数名称 : void IIC1_SendByte(uint8_t dat)
//* 函数描述 : 向设备发送一个数据
//* 输入参数 :
//* 参数描述 :
//* 输出参数 : 无
//* 返回值 : 无
//******************************************************************************
uint8_t IIC1_SendByte(uint8_t dat)
{
uint8_t datsendbit;
uint8_t RecvACK;
for (uint8_t i=0; i<8; i++) //8位计数器
{
datsendbit = ((dat & 0x80) >> 7);
dat <<= 1; //移出数据的最高位
if(datsendbit == 1)
{
IIC1_SDA_SET;
}
if(datsendbit == 0)
{
IIC1_SDA_RESET;
} //送数据口
delay_us(8);
IIC1_SCL_SET; //拉高时钟线
delay_us(8); //延时
IIC1_SCL_RESET; //拉低时钟线
delay_us(8);
}
RecvACK = IIC1_RecvACK();
return RecvACK;
}
//******************************************************************************
//* 函数名称 : IIC1_RecvByte()
//* 函数描述 : IIC1接收一个数据
//* 输入参数 :dat
//* 参数描述 :
//* 输出参数 : 无
//* 返回值 : 无
//******************************************************************************
uint8_t IIC1_RecvByte(void)
{
uint8_t RecvDat = 0;
IIC1_SDA_INITIn;
for (uint8_t i=0; i<8; i++) //8位计数器
{
RecvDat <<= 1;
IIC1_SCL_SET; //拉高时钟线
delay_us(10); //延时
RecvDat |= (IIC1_ReadSDA);
IIC1_SCL_RESET; //拉低时钟线
delay_us(10); //延时
}
IIC1_SDA_INITOut;
return RecvDat;
}
//******************************************************************************
//* 函数名称 : void IIC1_SendByte(uint8_t dat)
//* 函数描述 : IIC1向设备发送多个数据
//* 输入参数 :
//* 参数描述 :
//* 输出参数 : 无
//* 返回值 : 无
//******************************************************************************
void IIC1_SendBytes(uint8_t len,uint8_t* dat,uint8_t dev_addr)
{
uint8_t ack = 0;
IIC1_IIC_Start();
IIC1_SendByte(dev_addr<<1);
for(uint8_t i = 0; i < len; i++)
{
ack = IIC1_SendByte(*(dat+i));
}
IIC1_IIC_Stop();
}
//******************************************************************************
//* 函数名称 : IIC1_SendBytes
//* 函数描述 : IIC1从设备接收多个数据
//* 输入参数 :
//* 参数描述 :
//* 输出参数 : 无
//* 返回值 : 无
//******************************************************************************
void IIC1_RecvBytes(uint8_t len,uint8_t* dat,uint8_t dev_addr)
{
IIC1_IIC_Start();
IIC1_SendByte((dev_addr<<1)+1);
for(uint8_t i = 0; i < len; i++)
{
*(dat+i) = IIC1_RecvByte();
if(i == (len - 1))
{
IIC1_SendACK(1);
}
else
{
IIC1_SendACK(0);
}
}
IIC1_IIC_Stop();
}
//******************************************************************************
//* 函数名称 : void IIC1_US_SendBytes(uint8_t dat)
//* 函数描述 : IIC1向设备固定开始地址连续发送数据
//* 输入参数 :
//* 参数描述 :
//* 输出参数 : 无
//* 返回值 : 无
//******************************************************************************
void IIC1_US_SendBytes(uint8_t len,uint8_t* dat,uint8_t dev_addr,uint8_t reg_addr)
{
uint8_t ack = 0;
IIC1_IIC_Start();
IIC1_SendByte(dev_addr<<1);
IIC1_SendByte(reg_addr);
for(uint8_t i = 0; i < len; i++)
{
ack = IIC1_SendByte(*(dat+i));
}
IIC1_IIC_Stop();
}
//******************************************************************************
//* 函数名称 : IIC1_US_RecvBytes
//* 函数描述 : IIC1从设备固定地址连续接收数据
//* 输入参数 :
//* 参数描述 :
//* 输出参数 : 无
//* 返回值 : 无
//******************************************************************************
void IIC1_US_RecvBytes(uint8_t len,uint8_t* dat,uint8_t dev_addr,uint8_t reg_addr)
{
IIC1_IIC_Start();
IIC1_SendByte(dev_addr<<1);
IIC1_SendByte(reg_addr);
IIC1_IIC_Start();
IIC1_SendByte((dev_addr<<1)+1);
for(uint8_t i = 0; i < len; i++)
{
*(dat+i) = IIC1_RecvByte();
if(i == (len - 1))
{
IIC1_SendACK(1);
}
else
{
IIC1_SendACK(0);
}
}
IIC1_IIC_Stop();
}
硬件IIC测试了一下,没有完全成功,能够读取到数据但是是错误的,这个比读出来都是FF进了一步,而且还需要分别设计这两种传感器的模式,和软件模拟的方式并没有明显的优势,,所以也就不纠结了,也洗完大家可以帮忙指针一下问题。
硬件IIC代码如下:
//******************************************************************************
//* 函数名称 : IIC1_IOInit
//* 函数描述 : IIC1初始化及IO口初始化
//* 输入参数 :
//* 参数描述 :
//* 输出参数 : 无
//* 返回值 : 无
//******************************************************************************
void IIC1_IOInit(void)
{
I2C_InitType i2c1_master;
GPIO_InitType i2c1_gpio;
RCC_APB1_Peripheral_Clock_Enable(RCC_APB1_PERIPH_I2C1);
RCC_AHB_Peripheral_Clock_Enable(IIC1_MASTER_PERIPH_GPIO);
GPIO_Structure_Initialize(&i2c1_gpio);
/*PD13 -- SCL; PD12 -- SDA*/
i2c1_gpio.Pin = IIC1_MASTER_SDA_PIN | IIC1_MASTER_CLK_PIN;
i2c1_gpio.GPIO_Slew_Rate = GPIO_SLEW_RATE_FAST;
i2c1_gpio.GPIO_Mode = GPIO_MODE_AF_OD;
i2c1_gpio.GPIO_Alternate = GPIO_AF7_I2C1;
i2c1_gpio.GPIO_Pull = GPIO_PULL_UP;
GPIO_Peripheral_Initialize(IIC1_MASTER_GPIO, &i2c1_gpio);
I2C_Reset(I2C1);
I2C_Initializes_Structure(&i2c1_master);
i2c1_master.BusMode = I2C_BUSMODE_I2C;
i2c1_master.DutyCycle = I2C_SMDUTYCYCLE_1;
i2c1_master.OwnAddr1 = 0x76;
i2c1_master.AckEnable = I2C_ACKEN;
i2c1_master.AddrMode = I2C_ADDR_MODE_7BIT;
i2c1_master.ClkSpeed = 100000; /* 100k */
I2C_Initializes(I2C1, &i2c1_master);
I2C_ON(I2C1);
}
//******************************************************************************
//* 函数名称 : IIC1_IIC_Init()
//* 函数描述 : IIC初始化
//* 输入参数 :
//* 参数描述 :
//* 输出参数 : 无
//* 返回值 : 无
//******************************************************************************
void IIC1_IIC_Init(void)
{
I2C_Generate_Stop_Enable(I2C1);
}
//******************************************************************************
//* 函数名称 : void IIC1_SendBytes(uint8_t dat)
//* 函数描述 : IIC1向设备固定开始地址连续发送数据
//* 输入参数 :
//* 参数描述 :
//* 输出参数 : 无
//* 返回值 : 无
//******************************************************************************
void IIC1_SendBytes(uint8_t len,uint8_t* dat,uint8_t dev_addr)
{
uint8_t* sendBufferPtr = dat;
I2CTimeout = I2CT_LONG_TIMEOUT;
while (I2C_Flag_Status_Get(I2C1, I2C_FLAG_BUSY))
{
if ((I2CTimeout--) == 0)
{
break;
}
}
I2C_Generate_Start_Enable(I2C1);
I2CTimeout = I2CT_LONG_TIMEOUT;
while (!I2C_Event_Check(I2C1, I2C_EVT_MASTER_MODE_FLAG)) /* EV5 */
{
if ((I2CTimeout--) == 0)
{
break;
}
}
I2C_7bit_Addr_Send(I2C1, dev_addr, I2C_DIRECTION_SEND);
I2CTimeout = I2CT_LONG_TIMEOUT;
while (!I2C_Event_Check(I2C1, I2C_EVT_MASTER_TXMODE_FLAG)) /* EV6 */
{
if ((I2CTimeout--) == 0)
{
break;
}
}
// I2C_Data_Send(I2C1,reg_addr);
// I2CTimeout = I2CT_LONG_TIMEOUT;
// while (!I2C_Event_Check(I2C1, I2C_EVT_MASTER_DATA_SENDING)) /* EV6 */
// {
// if ((I2CTimeout--) == 0)
// {
// break;
// }
// }
/* send data */
while (len-- > 0)
{
I2C_Data_Send(I2C1, *sendBufferPtr++);
I2CTimeout = I2CT_LONG_TIMEOUT;
while (!I2C_Event_Check(I2C1, I2C_EVT_MASTER_DATA_SENDING)) /* EV8 */
{
if ((I2CTimeout--) == 0)
{
break;
}
}
}
I2CTimeout = I2CT_LONG_TIMEOUT;
while (!I2C_Event_Check(I2C1, I2C_EVT_MASTER_DATA_SENDED)) /* EV8-2 */
{
if ((I2CTimeout--) == 0)
{
break;
}
}
I2C_Generate_Stop_Enable(I2C1);
while (I2C_Flag_Status_Get(I2C1, I2C_FLAG_BUSY))
{
if ((I2CTimeout--) == 0)
{
break;
}
}
}
//******************************************************************************
//* 函数名称 : IIC1_RecvBytes
//* 函数描述 : IIC1从设备固定地址连续接收数据
//* 输入参数 :
//* 参数描述 :
//* 输出参数 : 无
//* 返回值 : 无
//******************************************************************************
void IIC1_RecvBytes(uint8_t len,uint8_t* dat,uint8_t dev_addr)
{
uint8_t* recvBufferPtr = dat;
I2CTimeout = I2CT_LONG_TIMEOUT;
while (I2C_Flag_Status_Get(I2C1, I2C_FLAG_BUSY))
{
if ((I2CTimeout--) == 0)
{
break;
}
}
I2C_Acknowledg_Enable(I2C1);
/* send start */
I2C_Generate_Start_Enable(I2C1);
I2CTimeout = I2CT_LONG_TIMEOUT;
while (!I2C_Event_Check(I2C1, I2C_EVT_MASTER_MODE_FLAG)) /* EV5 */
{
if ((I2CTimeout--) == 0)
{
break;
}
}
/* send addr */
I2C_7bit_Addr_Send(I2C1, dev_addr, I2C_DIRECTION_RECV);
I2CTimeout = I2CT_LONG_TIMEOUT;
while (!I2C_Event_Check(I2C1, I2C_EVT_MASTER_RXMODE_FLAG)) /* EV6 */
{
if ((I2CTimeout--) == 0)
{
break;
}
}
// I2C_Data_Send(I2C1,reg_addr);
// I2CTimeout = I2CT_LONG_TIMEOUT;
// while (!I2C_Event_Check(I2C1, I2C_EVT_MASTER_DATA_SENDING)) /* EV6 */
// {
// if ((I2CTimeout--) == 0)
// {
// break;
// }
// }
if (len == 1)
{
I2C_Acknowledg_Disable(I2C1);
(void)(I2C1->STS1); /*/ clear ADDR */
(void)(I2C1->STS2);
I2C_Generate_Stop_Enable(I2C1);
I2CTimeout = I2CT_LONG_TIMEOUT;
while (!I2C_Flag_Status_Get(I2C1, I2C_FLAG_RXDATNE))
{
if ((I2CTimeout--) == 0)
{
break;
}
}
*recvBufferPtr++ = I2C_Data_Recv(I2C1);
len--;
}
else if (len == 2)
{
I2C1->CTRL1 |= 0x0800; /*/ set ACKPOS */
(void)(I2C1->STS1);
(void)(I2C1->STS2);
I2C_Acknowledg_Disable(I2C1);
I2CTimeout = I2CT_LONG_TIMEOUT;
while (!I2C_Flag_Status_Get(I2C1, I2C_FLAG_BYTEF))
{
if ((I2CTimeout--) == 0)
{
break;
}
}
I2C_Generate_Stop_Enable(I2C1);
*recvBufferPtr++ = I2C_Data_Recv(I2C1);
len--;
*recvBufferPtr++ = I2C_Data_Recv(I2C1);
len--;
}
else
{
I2C_Acknowledg_Enable(I2C1);
(void)(I2C1->STS1);
(void)(I2C1->STS2);
while (len)
{
if (len == 3)
{
I2CTimeout = I2CT_LONG_TIMEOUT;
while (!I2C_Flag_Status_Get(I2C1, I2C_FLAG_BYTEF))
{
if ((I2CTimeout--) == 0)
{
break;
}
}
I2C_Acknowledg_Disable(I2C1);
*recvBufferPtr++ = I2C_Data_Recv(I2C1);
len--;
I2CTimeout = I2CT_LONG_TIMEOUT;
while (!I2C_Flag_Status_Get(I2C1, I2C_FLAG_BYTEF))
{
if ((I2CTimeout--) == 0)
{
break;
}
}
I2C_Generate_Stop_Enable(I2C1);
*recvBufferPtr++ = I2C_Data_Recv(I2C1);
len--;
*recvBufferPtr++ = I2C_Data_Recv(I2C1);
len--;
break;
}
I2CTimeout = I2CT_LONG_TIMEOUT;
while (!I2C_Event_Check(I2C1, I2C_EVT_MASTER_DATA_RECVD_FLAG)) /* EV7 */
{
if ((I2CTimeout--) == 0)
{
break;
}
}
*recvBufferPtr++ = I2C_Data_Recv(I2C1);
len--;
}
}
I2CTimeout = I2CT_LONG_TIMEOUT;
while (I2C_Flag_Status_Get(I2C1, I2C_FLAG_BUSY))
{
if ((I2CTimeout--) == 0)
{
break;
}
}
}
//******************************************************************************
//* 函数名称 : void IIC1_US_SendBytes(uint8_t dat)
//* 函数描述 : IIC1向设备固定开始地址连续发送数据
//* 输入参数 :
//* 参数描述 :
//* 输出参数 : 无
//* 返回值 : 无
//******************************************************************************
void IIC1_US_SendBytes(uint8_t len,uint8_t* dat,uint8_t dev_addr,uint8_t reg_addr)
{
uint8_t* sendBufferPtr = dat;
I2CTimeout = I2CT_LONG_TIMEOUT;
while (I2C_Flag_Status_Get(I2C1, I2C_FLAG_BUSY))
{
if ((I2CTimeout--) == 0)
{
break;
}
}
I2C_Generate_Start_Enable(I2C1);
I2CTimeout = I2CT_LONG_TIMEOUT;
while (!I2C_Event_Check(I2C1, I2C_EVT_MASTER_MODE_FLAG)) /* EV5 */
{
if ((I2CTimeout--) == 0)
{
break;
}
}
I2C_7bit_Addr_Send(I2C1, dev_addr, I2C_DIRECTION_SEND);
I2CTimeout = I2CT_LONG_TIMEOUT;
while (!I2C_Event_Check(I2C1, I2C_EVT_MASTER_TXMODE_FLAG)) /* EV6 */
{
if ((I2CTimeout--) == 0)
{
break;
}
}
I2C_Data_Send(I2C1,reg_addr);
I2CTimeout = I2CT_LONG_TIMEOUT;
while (!I2C_Event_Check(I2C1, I2C_EVT_MASTER_DATA_SENDING)) /* EV6 */
{
if ((I2CTimeout--) == 0)
{
break;
}
}
/* send data */
while (len-- > 0)
{
I2C_Data_Send(I2C1, *sendBufferPtr++);
I2CTimeout = I2CT_LONG_TIMEOUT;
while (!I2C_Event_Check(I2C1, I2C_EVT_MASTER_DATA_SENDING)) /* EV8 */
{
if ((I2CTimeout--) == 0)
{
break;
}
}
}
I2CTimeout = I2CT_LONG_TIMEOUT;
while (!I2C_Event_Check(I2C1, I2C_EVT_MASTER_DATA_SENDED)) /* EV8-2 */
{
if ((I2CTimeout--) == 0)
{
break;
}
}
I2C_Generate_Stop_Enable(I2C1);
while (I2C_Flag_Status_Get(I2C1, I2C_FLAG_BUSY))
{
if ((I2CTimeout--) == 0)
{
break;
}
}
}
//******************************************************************************
//* 函数名称 : IIC1_US_RecvBytes
//* 函数描述 : IIC1从设备固定地址连续接收数据
//* 输入参数 :
//* 参数描述 :
//* 输出参数 : 无
//* 返回值 : 无
//******************************************************************************
void IIC1_US_RecvBytes(uint8_t len,uint8_t* dat,uint8_t dev_addr,uint8_t reg_addr)
{
uint8_t* recvBufferPtr = dat;
I2CTimeout = I2CT_LONG_TIMEOUT;
while (I2C_Flag_Status_Get(I2C1, I2C_FLAG_BUSY))
{
if ((I2CTimeout--) == 0)
{
break;
}
}
I2C_PEC_Position_Set(I2C1, I2C_PEC_POS_CURRENT);
I2C_Acknowledg_Enable(I2C1);
/* send start */
I2C_Generate_Start_Enable(I2C1);
I2CTimeout = I2CT_LONG_TIMEOUT;
while (!I2C_Event_Check(I2C1, I2C_EVT_MASTER_MODE_FLAG)) /* EV5 */
{
if ((I2CTimeout--) == 0)
{
break;
}
}
/* send addr */
I2C_7bit_Addr_Send(I2C1, dev_addr, I2C_DIRECTION_SEND);
I2CTimeout = I2CT_LONG_TIMEOUT;
while (!I2C_Event_Check(I2C1, I2C_EVT_MASTER_TXMODE_FLAG)) /* EV6 */
{
if ((I2CTimeout--) == 0)
{
break;
}
}
/** Clear EV6 by setting again the PE bit */
I2C_ON(I2C1);
/** Send the address to write to */
I2C_Data_Send(I2C1,reg_addr);
I2CTimeout = I2CT_LONG_TIMEOUT;
while (!I2C_Event_Check(I2C1, I2C_EVT_MASTER_DATA_SENDING)) /* EV6 */
{
if ((I2CTimeout--) == 0)
{
break;
}
}
/* send start */
I2C_Generate_Start_Enable(I2C1);
I2CTimeout = I2CT_LONG_TIMEOUT;
while (!I2C_Event_Check(I2C1, I2C_EVT_MASTER_MODE_FLAG)) /* EV5 */
{
if ((I2CTimeout--) == 0)
{
break;
}
}
I2C_7bit_Addr_Send(I2C1, dev_addr, I2C_DIRECTION_RECV);
/* Test on EV6 and clear it */
I2CTimeout = I2CT_LONG_TIMEOUT;
while (!I2C_Flag_Status_Get(I2C1, I2C_FLAG_ADDRF)) //EV6
{
if ((I2CTimeout--) == 0)
break;
}
if (len == 1)
{
I2C_Acknowledg_Disable(I2C1);
(void)(I2C1->STS1); /*/ clear ADDR */
(void)(I2C1->STS2);
/** Generates START condition to close communication */
I2C_Generate_Start_Enable(I2C1);
}
else
{
(void)(I2C1->STS1); /*/ clear ADDR */
(void)(I2C1->STS2);
}
while (len)
{
if(len <= 2)
{
if(len == 1)
{
/** Wait until RXNE flag is set */
I2CTimeout = I2CT_LONG_TIMEOUT;
while (!I2C_Event_Check(I2C1, I2C_EVT_MASTER_DATA_RECVD_FLAG))
{
if ((I2CTimeout--) == 0)
break;
}
/** Read data from DAT */
*recvBufferPtr = I2C_Data_Recv(I2C1);
/** Point to the next location where the byte read will be saved */
recvBufferPtr++;
/** Decrement the read bytes counter */
len--;
/** Generates STOP condition to release SCL/SDA line */
I2C_Generate_Stop_Enable(I2C1);
}
else
{
/** Wait until RXNE flag is set */
I2CTimeout = I2CT_LONG_TIMEOUT;
while (!I2C_Event_Check(I2C1, I2C_EVT_MASTER_DATA_RECVD_FLAG))
{
if ((I2CTimeout--) == 0)
break;
}
/** Disable Acknowledgement */
I2C_Acknowledg_Disable(I2C1);
/** Read data from DAT */
*recvBufferPtr = I2C_Data_Recv(I2C1);
/** Point to the next location where the byte read will be saved */
recvBufferPtr++;
/** Decrement the read bytes counter */
len--;
/** Generates START condition to close communication */
I2C_Generate_Start_Enable(I2C1);
while (!I2C_Event_Check(I2C1, I2C_EVT_MASTER_DATA_RECVD_FLAG))
{
if((I2CTimeout--) == 0)
break;
}
/** Read data from DAT */
*recvBufferPtr = I2C_Data_Recv(I2C1);
/** Point to the next location where the byte read will be saved */
recvBufferPtr++;
/** Decrement the read bytes counter */
len--;
/** Generates STOP condition to release SCL/SDA line */
I2C_Generate_Stop_Enable(I2C1);
}
}
else
{
/** Test on EV7 and clear it */
I2CTimeout = I2CT_LONG_TIMEOUT;
while (!I2C_Event_Check(I2C1, I2C_EVT_MASTER_DATA_RECVD_FLAG))
{
if((I2CTimeout--) == 0)
break;
}
/** Read a byte from the EEPROM */
*recvBufferPtr = I2C_Data_Recv(I2C1);
/** Point to the next location where the byte read will be saved */
recvBufferPtr++;
/** Decrement the read bytes counter */
len--;
if (I2C_Flag_Status_Get(I2C1, I2C_FLAG_BYTEF))
{
/** Read a byte from the EEPROM */
*recvBufferPtr = I2C_Data_Recv(I2C1);
/** Point to the next location where the byte read will be saved */
recvBufferPtr++;
/** Decrement the read bytes counter */
len--;
}
}
}
}
在进行传感器数据采集时出现了一个插曲,FLASH超了,本次测评的MCU只有64K的FLASH,所以使用的全彩的论坛图标就显得有点大了,只能忍痛去掉了。
三、串口测试
这次的串口测试主要通过与NB-Iot模块的通信进行,获取模块的两个重要的身份识别码。本次依然采用空闲中断+DMA的方式进行,这种方式非常适用这种不定长的串口通信过程,大大减小多次串口中断对系统运行的干扰,由于时间原因,没有继续探究,串口通信没成功。
在这里发现了一个困扰,如下图:
同样是DMA的demo,USART2的Tx对应的通道确实不一样的,在用户手册中也没有完整的对应关系,0x03: USART2_TX 0x04: USART2_RX,和demo中表述模式是不一样,这样很容易产生歧义,在之前也有提到,驱动程序中对各个字段的定义也是不全面的,对于小白来说很不友好。
串口初始化代码:
//******************************************************************************
//* 函数名称 : USART2_init
//* 函数描述 : 串口2的初始化
//* 输入参数 :
//* 参数描述 : 对应 引脚初始化及配置
//* 输出参数 : 无
//* 返回值 : 无
//******************************************************************************
void USART2_init(void)
{
GPIO_InitType GPIO_InitStructure;
NVIC_InitType NVIC_InitStructure;
USART_InitType USART_InitStructure;
/* Initialize GPIO_InitStructure */
RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOA);
RCC_APB2_Peripheral_Clock_Enable(RCC_APB2_PERIPH_AFIO);
RCC_APB1_Peripheral_Clock_Enable(RCC_APB1_PERIPH_USART2);
GPIO_Structure_Initialize(&GPIO_InitStructure);
/* Configure USARTz Tx as alternate function push-pull */
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.Pin = GPIO_PIN_3|GPIO_PIN_2;
GPIO_InitStructure.GPIO_Alternate = GPIO_AF5_USART2;
GPIO_Peripheral_Initialize(GPIOA, &GPIO_InitStructure);
/* USART2 configuration---------*/
USART_InitStructure.BaudRate = 115200;
USART_InitStructure.WordLength = USART_WL_8B;
USART_InitStructure.StopBits = USART_STPB_1;
USART_InitStructure.Parity = USART_PE_NO;
USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
USART_InitStructure.Mode = USART_MODE_RX | USART_MODE_TX;
USART_Initializes(USART2, &USART_InitStructure);
/* Enable the USARTy Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Initializes(&NVIC_InitStructure);
USART2_DMA1_config();
USART_DMA_Transfer_Enable(USART2,USART_DMAREQ_RX);
/* Enable USARTz Receive and Transmit interrupts */
USART_Interrput_Enable(USART2, USART_INT_IDLEF);
USART_Enable(USART2);
}
//******************************************************************************
//* 函数名称 : USART2_DMA1_config
//* 函数描述 : 串口2 DMA接收配置
//* 输入参数 :
//* 参数描述 : 对应 引脚初始化及配置
//* 输出参数 : 无
//* 返回值 : 无
//******************************************************************************
void USART2_DMA1_config(void)
{
DMA_InitType DMA_InitStructure;
/* DMA clock enable */
RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_DMA);
/* USARTy TX DMA1 Channel (triggered by USARTy Tx event) Config */
DMA_Reset(DMA_CH4);
DMA_InitStructure.PeriphAddr = (uint32_t)&(USART2->DAT);
DMA_InitStructure.MemAddr = (uint32_t)USART2RecePackBuf;
DMA_InitStructure.Direction = DMA_DIR_PERIPH_SRC;//外设到内存
DMA_InitStructure.BufSize = 64;
DMA_InitStructure.PeriphInc = DMA_PERIPH_INC_MODE_DISABLE;//外设地址不增加
DMA_InitStructure.MemoryInc = DMA_MEM_INC_MODE_ENABLE;//内存地址递增
DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_WIDTH_BYTE;//外设数据长度
DMA_InitStructure.MemDataSize = DMA_MEM_DATA_WIDTH_BYTE;//8位数据
DMA_InitStructure.CircularMode = DMA_CIRCULAR_MODE_DISABLE;
DMA_InitStructure.Priority = DMA_CH_PRIORITY_HIGHEST;//最高DMA通道
DMA_InitStructure.Mem2Mem = DMA_MEM2MEM_DISABLE;
DMA_Initializes(DMA_CH4, &DMA_InitStructure);
DMA_Channel_Request_Remap(DMA_CH4,DMA_REMAP_USART2_RX);
/* Enable USART RX DMA Channel */
DMA_Channel_Enable(DMA_CH4);
}
总感觉缺点东西,网上的资料也非常少。
经过不断的定位测试发现还是DMA没有正常,不过配置都是正确的,少了一个USART_DMA_Transfer_Enable(USART2,USART_DMAREQ_RX);,加上后就能实现空闲中断加DMA收不定长数据了。进过测试确定CH4通道对应串口2的Rx是正确的,所以DMA_Polling对应的配置有误。
综合视频:
DSC_0167
|