【灵动微电子MM32F0121测评】2、串口打印&接收不定长UART消息
本文目标实现MM32F0121的串口收发功能。并且使用空闲中断(IDLE)方式实现了接收不定长UART消息。1、整理下评测用程序
主函数调用评测demo函数
int main(void)
{
PLATFORM_Init();
EVAL_Demo();
while (1)
{
}
}
DEMO函数中根据EVAL_DEMO定义决定运行哪个DEMO
void EVAL_Demo(void)
{
switch(EVAL_DEMO)
{
case 1:
GPIO_LED_Toggle_Sample();
break;
case 2:
UART_Sample();
break;
}
}/*
* 1:LED
* 2:UART
*/
#define EVAL_DEMO 2
本例中EVAL_DEMO定义为2
2、PLATFORM_Init修改
因为需要自己处理UART,所以将PLATFORM_Init中UART初始化部分注释掉,只保留LED初始化部分
void PLATFORM_Init(void)
{
PLATFORM_InitDelay();
//PLATFORM_InitConsole(115200);
PLATFORM_InitLED();
//PLATFORM_PrintInfo();
}
3、增加个uart_demo.c负责uart相关处理
1)USART初始化
使用USART1,TX:PB6,RX:PB7,
使用USART1的原因是USART1和板载调试器已相连,不用外接串口工具
USART1配置为双向收发
USART_IT_PE、USART_IT_ERR、USART_IT_IDLE、USART_IT_RXNE中断使能
USART_IT_IDLE使能用于实现接收不定长UART消息
void USART_Configure(uint32_t Baudrate)
{
GPIO_InitTypeDefGPIO_InitStruct;
NVIC_InitTypeDefNVIC_InitStruct;
USART_InitTypeDef USART_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
USART_StructInit(&USART_InitStruct);
USART_InitStruct.USART_BaudRate = Baudrate;
USART_InitStruct.USART_WordLength = USART_WordLength_8b;
USART_InitStruct.USART_StopBits = USART_StopBits_1;
USART_InitStruct.USART_Parity = USART_Parity_No;
USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_Init(USART1, &USART_InitStruct);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_0);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_0);
GPIO_StructInit(&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_High;
GPIO_InitStruct.GPIO_Mode= GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_StructInit(&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStruct.GPIO_Mode= GPIO_Mode_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStruct);
NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
USART_ITConfig(USART1, USART_IT_PE, DISABLE);
USART_ITConfig(USART1, USART_IT_ERR, DISABLE);
USART_ITConfig(USART1, USART_IT_CTS, DISABLE);
USART_ITConfig(USART1, USART_IT_TC, DISABLE);
USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
USART_Cmd(USART1, ENABLE);
}
2)定义收发数据处理数据结构
typedef struct
{
uint8_t Buffer;//缓冲
uint8_t Length; //最大长度
uint8_t CurrentCount;//当前缓冲指针位置
uint8_t CompleteFlag;//完成标志
} USART_RxTx_TypeDef;
volatile USART_RxTx_TypeDef USART_RxStruct;
volatile USART_RxTx_TypeDef USART_TxStruct;
3)USART接收处理函数
函数中Length参数为要接收数据的长度,此函数对USART_RxStruct进行了初始化,然后通过
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);使能接收中断
void USART_RxData_Interrupt(uint8_t Length)
{
uint8_t i = 0;
for (i = 0; i < Length; i++)
{
USART_RxStruct.Buffer = 0;
}
USART_RxStruct.Length = Length;
USART_RxStruct.CurrentCount = 0;
USART_RxStruct.CompleteFlag = 0;
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
}4)USART发送处理函数
Buffer发送数据指针,Length为发送数据长度
USART_ITConfig(USART1, USART_IT_TXE, ENABLE);使能发送中断
void USART_TxData_Interrupt(uint8_t *Buffer, uint8_t Length)
{
uint8_t i = 0;
for (i = 0; i < Length; i++)
{
USART_TxStruct.Buffer = Buffer;
}
USART_TxStruct.Length = Length;
USART_TxStruct.CurrentCount = 0;
USART_TxStruct.CompleteFlag = 0;
USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
}
4、中断处理函数(mm32f0120_it.c)
void USART1_IRQHandler(void)
{
uint8_t RxData = 0;
if ((RESET != USART_GetITStatus(USART1, USART_IT_PE)) ||
(RESET != USART_GetITStatus(USART1, USART_IT_ERR)))
{
USART_ReceiveData(USART1);
}
if (RESET != USART_GetITStatus(USART1, USART_IT_RXNE))
{
RxData = USART_ReceiveData(USART1);
if (0 == USART_RxStruct.CompleteFlag)
{
USART_RxStruct.Buffer = RxData;
PLATFORM_LED_Toggle(LED2);
}
}
if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)
{
// 检测到空闲中断,表示一帧数据接收完成
USART_ReceiveData(USART1); // 读取数据寄存器清除中断
USART_ClearITPendingBit(USART1, USART_IT_IDLE);
// 处理接收到的完整消息
// ...
if(USART_RxStruct.CurrentCount>0){
USART_ITConfig(USART1, USART_IT_IDLE, DISABLE);
USART_RxStruct.CompleteFlag = 1;
PLATFORM_LED_Toggle(LED1);
USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);
}
}
if (RESET != USART_GetITStatus(USART1, USART_IT_TXE))
{
if (0 == USART_TxStruct.CompleteFlag)
{
USART_SendData(USART1, USART_TxStruct.Buffer);
if (USART_TxStruct.CurrentCount == USART_TxStruct.Length)
{
USART_TxStruct.CompleteFlag = 1;
USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
}
}
}
}通过前面定义可知USART_IT_PE、USART_IT_ERR、USART_IT_IDLE、USART_IT_RXNE、USART_IT_TXE都会导致进入中断
1、USART_IT_PE (奇偶校验错误中断)、USART_IT_ERR (错误中断)
这两个中断主要处理一些错误情况。
2、USART_IT_RXNE处理接收数据,每接收一个字节,保存在缓冲的CurrentCount所指位置
3、USART_IT_TXE处理发送数据,在USART_IT_TXE使能并且CompleteFlag标识为发送完成情况下,按字节发送缓冲中的数据,当达到Length长度时,设置发送完成标识,设置USART_IT_TXE失能。
4、USART_IT_IDLE (空闲中断)
当检测到总线空闲(接收到一帧数据后,总线保持高电平超过一个完整数据帧时间)触发。
先清除中断标识:
USART_ReceiveData(USART1); // 读取数据寄存器清除中断
USART_ClearITPendingBit(USART1, USART_IT_IDLE);
没有接收到数据时也会进入USART_IT_IDLE中断,所以先判断一下USART_RxStruct.CurrentCount>0,保证是在USART_IT_RXNE中断之后触发的USART_IT_IDLE中断。
实行失能USART_IT_IDLE中断,设置接收数据完成标志CompleteFlag,失能USART_IT_RXNE
if(USART_RxStruct.CurrentCount>0){
USART_ITConfig(USART1, USART_IT_IDLE, DISABLE);
USART_RxStruct.CompleteFlag = 1;
PLATFORM_LED_Toggle(LED1);
USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);
}
5、写个DEMO运行一下
因为在platform.c以及对USART1做了printf重定义所以可以直接用printf
void Welcome_Info(void)
{
printf("请输入你的选择:\r\n");
printf("=========================\r\n");
printf("【1】:显示Hello 5次\r\n");
printf("【2】:显示不定长UART接收\r\n");
printf("【help】:显示本内容\r\n");
printf("【其他输入】:输入内容串口回显\r\n");
}
回显函数Echo_Back:就是在接收到非命令的RX串口数据后,将原数据通过TX发送回去,使用中断方式,通过USART_TxStruct.CompleteFlag判断是否完成:
void Echo_Back(void)
{
USART_TxData_Interrupt((uint8_t *)USART_RxStruct.Buffer, USART_RxStruct.CurrentCount);
while(USART_TxStruct.CompleteFlag!=1){};
}
RX接收后处理函数:
收到1,显示5次“Hello 21ic, Hello MM32F0121”
收到2,显示“输入2显示:这是不定长UART接收DEMO”
收到help,显示Welcome_Info()打印内容
收到其他,原数据回显
void Process_Input(void)
{
int i;
if(USART_RxStruct.CurrentCount==3){
if(USART_RxStruct.Buffer=='1'){
printf("输入1显示hello信息:\r\n");
for(i=0;i<5;i++)
{
USART_TxData_Interrupt((uint8_t *)"Hello 21ic, Hello MM32F0121\r\n",29);
PLATFORM_DelayMS(500);
}
}else if(USART_RxStruct.Buffer=='2'){
USART_TxData_Interrupt((uint8_t *)"输入2显示:这是不定长UART接收DEMO\r\n",35);
}else{
Echo_Back();
}
}else if(strstr((char*)USART_RxStruct.Buffer,"help"))
{
Welcome_Info();
}else{
Echo_Back();
}
USART_RxData_Interrupt(255);
USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);
}UART_Sample
void UART_Sample(void)
{
USART_RxStruct.CompleteFlag = 0;
USART_TxStruct.CompleteFlag = 1;
USART_Configure(115200);
printf("【MM32F0121开发板评测】2、串口打印\r\n");
Welcome_Info();
USART_RxData_Interrupt(255);
while(1)
{
if (1== USART_RxStruct.CompleteFlag&&USART_RxStruct.CurrentCount>0)
{
USART_RxStruct.CompleteFlag=0;
Process_Input();
}
}
}
6、运行
请教一下为什么我一直进if (RESET != USART_GetITStatus(USART1, USART_IT_IDLE))这个空闲中断条件,配置也搞成和你文档中一样了,串口助手没有发数据也一直进
页:
[1]