#include "usart.h"
UCHAR arr_rxData[1024]={0};//存储串口接收的数据
UINT arr_len=0;//串口已经接收数据的字节数个数
USART_RX_FLAG rxFlg=FLASE;//默认串口未接收到数据
void USART2_Init(void)
{
rcu_periph_clock_enable(RCU_GPIOB); //enable GPIO clock
rcu_periph_clock_enable(RCU_USART2);// enable USART clock
gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_10); // USARTx_Tx
gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_11);//USARTx_Rx
usart_deinit(USART2); //USART configure
usart_baudrate_set(USART2, 115200); //设置波特率
usart_word_length_set(USART2, USART_WL_8BIT); //设置数据位
usart_parity_config(Uusart_hardware_flow_rts_config(USART2, USART_RTS_DISABLE);
usart_hardware_flow_cts_config(USART2, USART_CTS_DISABLE); //无硬件数据流控制
usart_receive_config(USART2, USART_RECEIVE_ENABLE); //使能接收器
usart_transmit_config(USART2, USART_TRANSMIT_ENABLE); //使能发送器
nvic_irq_enable(USART2_IRQn, 1, 0);//配置NVIC分组,初始化NVIC分组4
usart_interrupt_enable(USART2, USART_INT_RBNE);//使能接收中断
usart_enable(USART2);//使能串口
}
int fputc(int ch, FILE *f)
{
while(RESET == usart_flag_get(USART2, USART_FLAG_TBE));
usart_data_transmit(USART2, (uint8_t)ch);
return ch;
}
/****************************************************************************
1、如果使能接收中断但是还是没有进入中断处理函数,可能是硬件接线比较松,导致出现问题
2、接收数据代码书写
if(rxFlg==TRUE)//表示接受一次数据完成
{
printf("receive data:%s\r\n",arr_rxData);
//将接收数据的标志位,数据长度,存储数据数组都清0
rxFlg=FLASE;
arr_len=0;
memset(arr_rxData,0,sizeof(arr_rxData));
}
******************************************************************************/
void USART2_IRQHandler(void)
{
if(RESET != usart_interrupt_flag_get(USART2, USART_INT_FLAG_RBNE)){
arr_rxData[arr_len++]=usart_data_receive(USART2);
if(arr_rxData[arr_len-1]==0x0a)
{
rxFlg=TRUE;
arr_len--;
arr_rxData[arr_len]='\0';
}
}
//usart_interrupt_flag_clear(USART2, USART_INT_FLAG_RBNE);
/*清除中断标志位,不用手动清除中断标志位,因为不管是直接读寄存器还是通过DMA,只要是对USART_DATA寄存器的一个读操作都可以硬件自动清除RBNE位*/
}
对于串口接收到的数据,还有很重要的一点就是不确定长度,这样就不知道何时该停止接收,这个时候,串口的空闲中断就体现出他的重要性了,那么什么是空闲中断呢?
空闲中断是在检测到有数据接收后,总线上在一个字节的时间内没有再接收到数据时,从而产生中断。即串口的RXNE位被置位之后才开始检测,检测到空闲之后,串口的CR1寄存器的IDLE位被硬件置1。
#include "usart.h"
UCHAR arr_rxData[1024]={0};//存储串口接收的数据
UINT arr_len=0;//串口已经接收数据的字节数个数
USART_RX_FLAG rxFlg=FLASE;//默认串口未接收到数据
void USART2_Init(void)
{
rcu_periph_clock_enable(RCU_GPIOB); //enable GPIO clock
rcu_periph_clock_enable(RCU_USART2);// enable USART clock
gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_10); // USARTx_Tx
gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_11);//USARTx_Rx
usart_deinit(USART2); //USART configure
usart_baudrate_set(USART2, 115200); //设置波特率
usart_word_length_set(USART2, USART_WL_8BIT); //设置数据位
usart_parity_config(Uusart_hardware_flow_rts_config(USART2, USART_RTS_DISABLE);
usart_hardware_flow_cts_config(USART2, USART_CTS_DISABLE); //无硬件数据流控制
usart_receive_config(USART2, USART_RECEIVE_ENABLE); //使能接收器
usart_transmit_config(USART2, USART_TRANSMIT_ENABLE); //使能发送器
nvic_irq_enable(USART2_IRQn, 1, 0);//配置NVIC分组,初始化NVIC分组4
usart_interrupt_enable(USART2, USART_INT_RBNE);//使能接收中断
usart_enable(USART2);//使能串口
}
int fputc(int ch, FILE *f)
{
while(RESET == usart_flag_get(USART2, USART_FLAG_TBE));
usart_data_transmit(USART2, (uint8_t)ch);
return ch;
}
void USART2_IRQHandler(void)
{
if(RESET != usart_interrupt_flag_get(USART2, USART_INT_FLAG_RBNE)){
arr_rxData[arr_len++]=usart_data_receive(USART2);
}
if(RESET != usart_interrupt_flag_get(USART2, USART_INT_FLAG_IDLE))
{
usart_interrupt_flag_clear(USART2,USART_INT_FLAG_IDLE); /* 清除空闲中断标志位 */
usart_data_receive(USART2);
rxFlg=TRUE;
arr_len--;
arr_rxData[arr_len]='\0';
}
}
对于串口的数据接收来说,和发送一样,如果采用传统的接收中断模式接收数据,同样的会因为频繁中断而导致消耗大量CPU资源,所以也使用DMA进行串口数据的接收。
#define USART2_ADDR (uint32_t)&USART_DATA(USART2)
UCHAR UART2_RX_BUF[UART2_RX_LEN*2]; /* 双接收缓冲区 */
USART_RX_FLAG UART2_RX_STAT = FLASE;
UINT UART2_RX_NUM = 0; /* 接收到的数据个数 */
void USART2_DMA_Init(void)
{
dma_parameter_struct dma_init_struct; /* DMA配置参数结构体 */
rcu_periph_clock_enable(RCU_GPIOB); //enable GPIO clock
rcu_periph_clock_enable(RCU_USART2);// enable USART clock
rcu_periph_clock_enable(RCU_DMA0); /* 使能 DMA0 时钟 */
gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_10);
gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_11);
usart_deinit(USART2); //USART configure
usart_baudrate_set(USART2, 115200); //设置波特率
usart_word_length_set(USART2, USART_WL_8BIT); //设置数据位
usart_parity_config(USART2, USART_PM_NONE); //设置奇偶校验位
usart_stop_bit_set(USART2, USART_STB_1BIT); //设置停止位
usart_hardware_flow_rts_config(USART2, USART_RTS_DISABLE); //禁用rts
usart_hardware_flow_cts_config(USART2, USART_CTS_DISABLE); //无硬件数据流控制
usart_receive_config(USART2, USART_RECEIVE_ENABLE); //使能接收器
usart_transmit_config(USART2, USART_TRANSMIT_ENABLE); //使能发送器
/* USART0 DMA 接收配置*/
dma_deinit(DMA0, DMA_CH2);/*USART2_RX:CH2 USART0_RX:CH4*/
dma_struct_para_init(&dma_init_struct);
dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY; /* 外设到存储器方向 */
dma_init_struct.memory_addr = (uint32_t)UART2_RX_BUF; /* 存储器基地址 */
dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; /* 存储器地址自增 */
dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; /* 存储器位宽为8位 */
dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH; /* 软件优先级为极高*/
dma_init(DMA0, DMA_CH2, &dma_init_struct);
dma_circulation_disable(DMA0, DMA_CH2);/* DMA循环模式配置,不使用循环模式 */
usart_dma_transmit_config(USART2, USART_DENT_ENABLE);
usart_dma_receive_config(USART2, USART_DENR_ENABLE);
nvic_irq_enable(DMA0_Channel2_IRQn, 0, 0);/* DMA0 通道2 中断优先级设置并使能 */
dma_channel_enable(DMA0, DMA_CH2);/* 使能 DMA0 通道2 */
nvic_irq_enable(USART2_IRQn, 1, 0);//配置NVIC分组,初始化NVIC分组4
usart_interrupt_enable(USART2, USART_INT_IDLE);/* 使能USART0空闲中断 */
usart_enable(USART2);//使能串口
}
/*
如果接收完毕,那么将数据打印出来
if(UART2_RX_STAT == TRUE)
{
UART2_RX_STAT = FLASE;
printf("RECEIVE %d data:%s \r\n", UART2_RX_NUM, UART2_RX_BUF);
}
*/
void USART2_IRQHandler(void)
{
if(RESET != usart_interrupt_flag_get(USART2, USART_INT_FLAG_IDLE)) //空闲中断
{
usart_interrupt_flag_clear(USART2,USART_INT_FLAG_IDLE); /* 清除空闲中断标志位 */
usart_data_receive(USART2); /* 清除接收完成标志位 */
dma_channel_disable(DMA0, DMA_CH2); /* 关闭DMA传输 */
UART2_RX_NUM = sizeof(UART2_RX_BUF) - dma_transfer_number_get(DMA0,DMA_CH2);
UART2_RX_BUF[UART2_RX_NUM] = '\0'; /* 添加字符串结束符 */
UART2_RX_STAT = TRUE;/* 接收完成 */
/* 重新设置DMA传输 */
dma_memory_address_config(DMA0,DMA_CH2,(uint32_t)UART2_RX_BUF);
dma_transfer_number_config(DMA0,DMA_CH2,sizeof(UART2_RX_BUF));
dma_channel_enable(DMA0, DMA_CH2); /* 开启DMA传输 */
}
}