μcos环境例程
freertos环境例程
重要几点
1.配置DMA,串口及环形buff之间的关系;
2.USART_IT_IDLE空闲中断接收完一帧数据,处理环形buff入口指针,通知用户程序接收完一次数据;
3.发送数据无需利用环形buff,直接将待传数据作为DMA的源地址,再使能相应DMA通道,根据串口TC中断判断发送完成;
4.用户程序中读取FIF0;
环形FIFO buff
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;
}
USART初始化
注意使能串口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初始化
使能相应的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数据不足则有多少回多少
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)