- //stm32f1 串口通信
- // 串口通信模块会为串口划分256字节的uart缓存区,缓存中断接收的数据,
- // 处理串口接收数据的任务会每50ms按协议处理解析缓存区里的数据。当然,
- // 如果没有处理完缓存区的数据,而又接收到新的数据,那新的数据将会被
- // 舍弃。
- // 串口的接收数据和发送数据都用到DMA处理器,其中串口接收用了串口
- // 空闲中断。串口连续接收数据后检测到串口接收空闲,产生一个空闲中断,
- // 这时候将接收到的数据缓存到uart缓存区中,等待解析。
- // 1. 配置串口IO口以及串口功能配置
- // 这里使用的是uart1
- #define FIFOLEN 256
- static uint8_t dma_buf[FIFOLEN];
- static uint8_t dma_rx[FIFOLEN];
- static u8 fifo_buf[FIFOLEN];
- static u16 fifo_in = 0;
- static u16 fifo_out = 0;
- static u16 fifo_used = 0;
- void uart1_func_init(void)
- {
- GPIO_InitTypeDef io;
- USART_InitTypeDef uart;
- //UART1 IO口配置
- io.GPIO_Pin = GPIO_Pin_9;
- io.GPIO_Mode= GPIO_Mode_AF_PP;
- io.GPIO_Speed= GPIO_Speed_50MHz;
- GPIO_Init(GPIOA, &io);
- io.GPIO_Pin = GPIO_Pin_10;
- io.GPIO_Mode= GPIO_Mode_IN_FLOATING;
- io.GPIO_Speed= GPIO_Speed_50MHz;;
- GPIO_Init(GPIOA, &io);
- //USART1 功能配置 波特率115200,8位数据位,1位停止位,无校验,无硬件流控制
- uart.USART_BaudRate = 115200;
- uart.USART_WordLength = USART_WordLength_8b;
- uart.USART_StopBits = USART_StopBits_1;
- uart.USART_Parity = USART_Parity_No;
- uart.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
- uart.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
- USART_Init(USART1, &uart);
- USART_ITConfig(USART1,USART_IT_TC,DISABLE);//使能串口空闲中断
- USART_ITConfig(USART1,USART_IT_RXNE,DISABLE);//失能接收中断
- USART_ITConfig(USART1,USART_IT_IDLE,ENABLE);//使能发送中断
- USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);//使能串口发送DMA
- USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);//使能串口接收DMA
- USART_Cmd(USART1, ENABLE);
- }
- // 2. 配置DMA功能
- // stm32f103手册里可以了解到,uart1-uart4有相关的DMA通道,对应如下
- // uart1_tx-->DMA1_Channel4 uart1_rx-->DMA1_Channel5
- // uart2_tx-->DMA1_Channel7 uart2_rx-->DMA1_Channel6
- // uart3_tx-->DMA1_Channel2 uart3_rx-->DMA1_Channel3
- // uart4_tx-->DMA2_Channel5 uart4_rx-->DMA2_Channel2
- static void uart1_dma_init(void)
- {
- DMA_InitTypeDef dma;
- //DMA 配置
- dma.DMA_BufferSize = 1; //初始化为1个字节
- dma.DMA_DIR = DMA_DIR_PeripheralDST; //从内存到外设
- dma.DMA_M2M = DMA_M2M_Disable; //内存到内存,失能
- dma.DMA_MemoryBaseAddr = (uint32_t)dma_buf; //内存地址
- dma.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //数据宽度
- dma.DMA_MemoryInc = DMA_MemoryInc_Enable; //使能自增
- dma.DMA_Mode = DMA_Mode_Normal; //普通模式,不连续模式
- dma.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR; //外设地址
- dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //数据宽度
- dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址不自增
- dma.DMA_Priority = DMA_Priority_High; //优先级
- DMA_DeInit(DMA1_Channel4);
- DMA_Init(DMA1_Channel4, &dma);
- DMA_Cmd(DMA1_Channel4, ENABLE);
- dma.DMA_PeripheralBaseAddr = (u32)(&USART1->DR);
- dma.DMA_MemoryBaseAddr = (uint32_t)dma_rx;
- dma.DMA_DIR = DMA_DIR_PeripheralSRC;
- dma.DMA_BufferSize = FIFOLEN;
- dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
- dma.DMA_MemoryInc = DMA_MemoryInc_Enable;
- dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
- dma.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
- dma.DMA_Mode = DMA_Mode_Normal;
- dma.DMA_Priority = DMA_Priority_VeryHigh;
- dma.DMA_M2M = DMA_M2M_Disable;
- DMA_DeInit(DMA1_Channel5);
- DMA_Init(DMA1_Channel5,&dma);
- DMA_Cmd(DMA1_Channel5,ENABLE);
- }
- void uart1_init(void)
- {
- uart1_dma_init();
- uart1_func_init();
- }
- //3. uart 缓存区用fifo方式存取
- u16 uart1_read(u8* data, u16 len)
- {
- u16 i;
- u16 ret;
- ret = (len < fifo_used) ? len : fifo_used;
- for(i = 0; i < ret; i++)
- {
- data[i] = fifo_buf[fifo_out];
- if(++fifo_out == FIFOLEN)
- {
- fifo_out = 0;
- }
- }
- fifo_used -= ret;
- return ret;
- }
- void uart1_write(uint8_t* data, uint16_t len)
- {
- uint16_t i;
- while(!DMA_GetFlagStatus(DMA1_FLAG_TC4));
- DMA_Cmd(DMA1_Channel4, DISABLE);
- for(i=0; i
- {
- dma_buf[i] = data[i];
- }
- DMA_ClearFlag(DMA1_FLAG_TC4);
- DMA_SetCurrDataCounter(DMA1_Channel4, len);
- DMA_Cmd(DMA1_Channel4, ENABLE);
- }
- //打印调试信息
- void uart1_puts(char* s)
- {
- u16 i;
- for(i=0;s[i]!=0;i++)
- {
- while(!USART_GetFlagStatus(USART1, USART_FLAG_TXE));
- USART_SendData(USART1, s[i]);
- }
- }
- void USART1_IRQHandler(void)
- {
- u16 temp;
- u16 i;
- if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)
- {
- temp = USART1->SR;//----清除空闲标志位
- temp = USART1->DR;
- DMA_Cmd(DMA1_Channel5,DISABLE);
- temp = FIFOLEN - DMA_GetCurrDataCounter(DMA1_Channel5);
- for(i=0; i
- {
- if(fifo_used
- {
- fifo_buf[fifo_in] = dma_rx[i];
- if(++fifo_in == FIFOLEN)
- {
- fifo_in = 0;
- }
- fifo_used++;
- }
- }
- DMA_SetCurrDataCounter(DMA1_Channel5,FIFOLEN);
- DMA_Cmd(DMA1_Channel5,ENABLE);
- }
- else
- {
- USART_ReceiveData(USART1);
- USART_ClearFlag(USART1, USART_FLAG_ORE);
- }
- }
|