赞
踩
μcos环境例程
freertos环境例程
重要几点
1.配置DMA,串口及环形buff之间的关系;
2.USART_IT_IDLE空闲中断接收完一帧数据,处理环形buff入口指针,通知用户程序接收完一次数据;
3.发送数据无需利用环形buff,直接将待传数据作为DMA的源地址,再使能相应DMA通道,根据串口TC中断判断发送完成;
4.用户程序中读取FIF0;
FIFO实现为一个维护入口下标和出口下标的数组,循环覆写,与DMA的循环模式类似
typedef struct {
uint8_t* buffer; //FIFO数据
uint16_t in; //入口下标
uint16_t out; //出口下标
uint16_t size; //FIFO大小
}FIFO_Type;
几个FIFO功能函数
void Fifo_Init(FIFO_Type* fifo, uint8_t* buffer, uint16_t size) { fifo->buffer = buffer; fifo->in = 0; fifo->out = 0; fifo->size = size; } uint16_t Fifo_Get(FIFO_Type* fifo, uint8_t* buffer, uint16_t len) { uint16_t lenght; uint16_t in = fifo->in; uint16_t i; lenght = (in + fifo->size - fifo->out)%fifo->size; if(lenght > len) lenght = len; for(i = 0; i < lenght; i++) { buffer[i] = fifo->buffer[(fifo->out + i)%fifo->size]; } fifo->out = (fifo->out + lenght)%fifo->size; return lenght; } uint16_t Fifo_Status(FIFO_Type* fifo) { uint16_t lenght; lenght = (fifo->in + fifo->size - fifo->out)%fifo->size; return lenght; }
注意使能串口TC中断,IDLE中断及串口DMA收发,分别标志传输完成和接受完成,其他配置为常规配置,根据自己需求配置即可,串口1为例
//GPIO端口设置 GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟 //USART1_TX GPIOA.9 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9 //USART1_RX GPIOA.10初始化 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入 GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10 //Usart1 NVIC 配置 NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器 //USART 初始化设置 USART_InitStructure.USART_BaudRate = 115200;//串口波特率 USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式 USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位 USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式 USART_Init(USART1, &USART_InitStructure); //初始化串口1 USART_ITConfig(USART1, USART_IT_IDLE , ENABLE);//空闲中断 USART_ITConfig(USART1, USART_IT_TC , ENABLE);//传输完成中断 USART_DMACmd(USART1, USART_DMAReq_Tx|USART_DMAReq_Rx, ENABLE);//使能串口DMA收发 USART_Cmd(USART1, ENABLE); //使能串口1
使能相应的DMA通道,通道表如下

如上表得知,串口1的DMA收发通道为DMA1的通道4通道5,初始化如下
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); DMA_DeInit(DMA1_Channel5); DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&USART1->DR); DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Uart1_Rx_Buffer; //FIFO的buffer指针指向 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = BSP_UART1_RX_SIZE; //FIF0的buffer大小 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //DMA循环覆盖写入 DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel5, &DMA_InitStructure); /* Enable USART1 DMA TX request */ DMA_Cmd (DMA1_Channel5,ENABLE); DMA_DeInit(DMA1_Channel4); DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART1->DR); DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)0; //传输再修改地址,并使能该通道 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_BufferSize = 1; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel4, &DMA_InitStructure); //接收FIFO初始化 Fifo_Init(&Uart1_Rx_Fifo,Uart1_Rx_Buffer,BSP_UART1_RX_SIZE); //同步量,RTOS相关 OSMutexCreate (&Uart1TxSem, "uart1 tx mutex", &err); OSSemCreate (&Uart1TxWaitSem, "uart1 tx wait sem", 0,&err);
处理串口TC中断,IDLE中断
void Bsp_IntHandler(CPU_FNCT_VOID isr)// RTOS相关 { CPU_SR_ALLOC(); CPU_CRITICAL_ENTER(); /* Tell the OS that we are starting an ISR */ OSIntEnter(); CPU_CRITICAL_EXIT(); if (isr != (CPU_FNCT_VOID)0) { isr(); } OSIntExit(); } void USART1_IRQHandler(void) //中断 { Bsp_IntHandler(USART1_IntHandler); } void USART1_IntHandler(void) // 中断服务函数 { uint32_t temp = 0; OS_ERR err; if(USART_GetITStatus(USART1,USART_IT_IDLE)!= RESET)//空闲中断 { Uart1_Rx_Fifo.in = BSP_UART1_RX_SIZE - DMA_GetCurrDataCounter(DMA1_Channel5); OSTaskSemPost(&MyTask_TCB, OS_OPT_POST_NONE, &err);//通知用户任务接收到一次数据帧 temp = USART1->SR; //软件序列清除IDLE位 temp = USART1->DR; //先读USART_SR,然后读USART_DR USART_ClearITPendingBit(USART1,USART_IT_IDLE); } else if(USART_GetITStatus(USART1,USART_IT_TC)!= RESET)//发送完成中断 { USART_ClearITPendingBit(USART1,USART_IT_TC); DMA_Cmd(DMA1_Channel4, DISABLE); OSSemPost (&Uart1TxWaitSem, OS_OPT_POST_NONE, &err); if(err != OS_ERR_NONE) { temp = err; } } }
发送,串口资源互斥访问,信号量通知串口发送成功
void Uart_Send(const uint8_t* buf, uint16_t len) { OS_ERR err; if(len > BSP_UART1_TX_SIZE || len == 0) { return; } OSMutexPend(&Uart1TxSem, 500, OS_OPT_PEND_BLOCKING, (CPU_TS *) 0, &err); OSSemSet(&Uart1TxWaitSem, 0, &err); if(err != OS_ERR_NONE) { return err; } DMA_Cmd(DMA1_Channel4, DISABLE); DMA1_Channel4->CNDTR = len;//发送数据大小 DMA1_Channel4->CMAR = (uint32_t)buf;//发送数据地址 /* Enable USART1 DMA TX request */ DMA_Cmd (DMA1_Channel4,ENABLE); OSSemPend(&Uart1TxWaitSem, 500, OS_OPT_PEND_BLOCKING, (CPU_TS *) 0, &err); OSMutexPost (&Uart1TxSem, OS_OPT_POST_NONE, &err); } uint16_t Uart_1_Get(uint8_t *buffer, uint16_t len) { return Fifo_Get(&Uart1_Rx_Fifo,buffer, len); //读出长度len的fifo中的数据存在buffer参数中,fifo数据不足则有多少回多少 }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。