完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
重要几点
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 = 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数据不足则有多少回多少 } |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1886 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1663 浏览 1 评论
1152 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
763 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1720 浏览 2 评论
1966浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
792浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
616浏览 3评论
631浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
594浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-1-15 06:00 , Processed in 0.629644 second(s), Total 44, Slave 38 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号