#include "../inc/system.h" #include "./USART.h" ////////////////////////////////////////////////////////////////// //加入以下代码,支持printf函数,而不需要选择use MicroLIB #if 1 #pragma import(__use_no_semihosting) //标准库需要的支持函数 struct __FILE { int handle; }; FILE __stdout; //定义_sys_exit()以避免使用半主机模式 void _sys_exit(int x) { x = x; } //重定义fputc函数 int fputc(int ch, FILE *f) { while((USART1->SR&0X80)==0);//循环发送,直到发送完毕 USART1->DR = (u8) ch; return ch; } #endif #ifndef USE_STM32F103_Cxxx define USE_STM32F103_Cxxx 1 //默认使用STM32F103Cxxxx三个串口 #endif #define Send_Buffer 1024 //设置发送缓冲区最大长度 #define Receive_Queue_Max_Length 1030 //设置接收队列缓冲区最大长度 #define Receive_Queue_ItemSize 1 //设置接收队列缓冲区单个数据大小 static uint8_t Receive_Queue_Buffer[Receive_Queue_Max_Length]; //设置接收队列缓冲区 static uint16_t Receive_Queue_Buffer_Count = 0; static void *Receive_Queue[Receive_Queue_Max_Length]; /* 串口私有数据结构体类型 */ typedef struct USART_PRIV_DATA { USART_TypeDef *USARTx; //串口号 OS_EVENT *xSemphr_Send; //发送完成信号量句柄 OS_EVENT *xSemphr_Receive; //接收数据帧信号量句柄 OS_EVENT *xQueue_Receive; //接收队列句柄 char SendBuffer[Send_Buffer]; //发送缓冲区 char *pSendBuffer; //指向发送缓冲区指针 } usart_priv_obj_t; /* 串口相关操作函数声明 */ static int usart_init(usart_obj_t *pDev, uint32_t BaudRate, uint16_t DataBit, float StopBit, uint16_t Parity); static void usart_deinit(usart_obj_t *pDev); static void usart_send(usart_obj_t *pDev, uint8_t *data, uint16_t dataLenght); static int usart_print(usart_obj_t *pDev, INT32U timeout_ms, char *format, ...); static int usart_receive(usart_obj_t *pDev, uint8_t *data, uint16_t data_len, uint16_t *rec_br, INT32U timeout_ms); static uint32_t usart_wait_message_count(usart_obj_t *pDev); static void usart_irq_handle(usart_obj_t *pDev); /* 串口1私有数据 */ static usart_priv_obj_t g_usart1_priv_data = { USART1, }; /* 串口1结构体对象 */ static usart_obj_t g_usart1 = { "usart1", usart_init, usart_deinit, usart_send, usart_print, usart_receive, usart_wait_message_count, &g_usart1_priv_data }; /* 串口2私有数据 */ static usart_priv_obj_t g_usart2_priv_data = { USART2, }; /* 串口2结构体对象 */ static usart_obj_t g_usart2 = { "usart2", usart_init, usart_deinit, usart_send, usart_print, usart_receive, usart_wait_message_count, &g_usart2_priv_data }; /* 串口3私有数据 */ static usart_priv_obj_t g_usart3_priv_data = { USART3, }; /* 串口3结构体对象 */ static usart_obj_t g_usart3 = { "usart3", usart_init, usart_deinit, usart_send, usart_print, usart_receive, usart_wait_message_count, &g_usart3_priv_data }; #if (USE_STM32F103_Cxxx != 1) /* 串口4私有数据 */ static usart_priv_obj_t g_usart4_priv_data = { UART4, }; /* 串口4结构体对象 */ static usart_obj_t g_uart4 = { "usart4", usart_init, usart_deinit, usart_send, usart_print, usart_receive, usart_wait_message_count, &g_usart4_priv_data }; /* 串口5私有数据 */ static usart_priv_obj_t g_usart5_priv_data = { UART5, }; /* 串口5结构体对象 */ static usart_obj_t g_uart5 = { "uart5", usart_init, usart_deinit, usart_send, usart_print, usart_receive, usart_wait_message_count, &g_usart5_priv_data }; #endif /* 串口设备列表 */ static usart_obj_t *g_usart_devs[] = { &g_usart1, &g_usart2, &g_usart3, #if(USE_STM32F103_Cxxx != 1) &g_uart4, &g_uart5, #endif }; static void USART_DMA_Config(void); /* *@函数名:usart_init *@函数功能:初始化指定串口 *@参数: * @pDev:指定串口句柄 * @BautRate:串口波特率 * value:9600、 14400、 19200、 38400、 115200、 256000、 921600 * @DataBit:串口数据位 * value:8、 9 * @StopBit:串口停止位 * value:0.5、 1、 1.5、 2 * @Parity:串口校验位 * value:0:无校验、 1:奇校验、 2:偶校验 *@返回值 * 0:串口初始化成功 * -1:串口初始化失败 */ static int usart_init(usart_obj_t *pDev, uint32_t BaudRate, uint16_t DataBit, float StopBit, uint16_t Parity) { usart_priv_obj_t *usart_priv_obj = pDev->usart_priv_data; /* 创建串口发送信号量和接收队列 */ usart_priv_obj->xQueue_Receive = OSQCreate(Receive_Queue, Receive_Queue_Max_Length); if (usart_priv_obj->xQueue_Receive == NULL) { printf("usart init fail %s %d\r\n", __FILE__, __LINE__); } usart_priv_obj->xSemphr_Send = OSSemCreate(0); if (usart_priv_obj->xSemphr_Send == NULL) { printf("usart init fail %s %d\r\n", __FILE__, __LINE__); } usart_priv_obj->xSemphr_Receive = OSSemCreate(0); if (usart_priv_obj->xSemphr_Receive == NULL) { printf("usart init fail %s %d\r\n", __FILE__, __LINE__); } /* 初始化不同串口不同的参数部分 */ uint32_t RCC_APBxPeriph_UARTx = NULL; uint32_t RCC_AHB1Periph_GPIOx = NULL; GPIO_TypeDef *GPIOx = NULL; uint16_t GPIO_PinSource_Tx; uint16_t GPIO_PinSource_Rx; uint8_t AF_Type; GPIO_InitTypeDef GPIO_InitStructure_Tx; GPIO_InitTypeDef GPIO_InitStructure_Rx; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; if(USART1 == usart_priv_obj->USARTx) { RCC_APBxPeriph_UARTx = RCC_APB2Periph_USART1; RCC_AHB1Periph_GPIOx = RCC_AHB1Periph_GPIOA; GPIOx = GPIOA; GPIO_PinSource_Tx = GPIO_PinSource9; GPIO_PinSource_Rx = GPIO_PinSource10; AF_Type = GPIO_AF_USART1; GPIO_InitStructure_Tx.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure_Rx.GPIO_Pin = GPIO_Pin_10; NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; } else if(USART2 == usart_priv_obj->USARTx) { RCC_APBxPeriph_UARTx = RCC_APB1Periph_USART2; RCC_AHB1Periph_GPIOx = RCC_AHB1Periph_GPIOA; GPIOx = GPIOA; GPIO_PinSource_Tx = GPIO_PinSource2; GPIO_PinSource_Rx = GPIO_PinSource3; AF_Type = GPIO_AF_USART2; GPIO_InitStructure_Tx.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure_Rx.GPIO_Pin = GPIO_Pin_3; NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; } else if(USART3 == usart_priv_obj->USARTx) { RCC_APBxPeriph_UARTx = RCC_APB1Periph_USART3; RCC_AHB1Periph_GPIOx = RCC_AHB1Periph_GPIOB; GPIOx = GPIOB; GPIO_PinSource_Tx = GPIO_PinSource10; GPIO_PinSource_Rx = GPIO_PinSource11; AF_Type = GPIO_AF_USART3; GPIO_InitStructure_Tx.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure_Rx.GPIO_Pin = GPIO_Pin_11; NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; } /* else if (UART4 == usart_priv_obj->USARTx) { }*/ // else{} /* 初始化串口数据位、停止位、校验位 */ switch(DataBit) { case 8:USART_InitStructure.USART_WordLength = USART_WordLength_8b; break; case 9:USART_InitStructure.USART_WordLength = USART_WordLength_9b; break; default:return -1; } if(0.5f == StopBit) USART_InitStructure.USART_StopBits = USART_StopBits_0_5; else if(1.0f == StopBit) USART_InitStructure.USART_StopBits = USART_StopBits_1; else if(1.5f == StopBit) USART_InitStructure.USART_StopBits = USART_StopBits_1_5; else if(2.0f == StopBit) USART_InitStructure.USART_StopBits = USART_StopBits_2; else return -1; switch(Parity) { case 0:USART_InitStructure.USART_Parity = USART_Parity_No; break; case 1:USART_InitStructure.USART_Parity = USART_Parity_Odd; break; case 2:USART_InitStructure.USART_Parity = USART_Parity_Even; break; default:return -1; } /* 初始化串口时钟、GPIO、NVIC */ if(USART1 == usart_priv_obj->USARTx) RCC_APB2PeriphClockCmd(RCC_APBxPeriph_UARTx, ENABLE); else RCC_APB1PeriphClockCmd(RCC_APBxPeriph_UARTx, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOx, ENABLE); GPIO_PinAFConfig(GPIOx, GPIO_PinSource_Tx, AF_Type); GPIO_PinAFConfig(GPIOx, GPIO_PinSource_Rx, AF_Type); GPIO_InitStructure_Tx.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure_Tx.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure_Rx.GPIO_PuPd = GPIO_PuPd_UP; GPIO_InitStructure_Tx.GPIO_Speed = GPIO_Speed_100MHz; GPIO_Init(GPIOx, &GPIO_InitStructure_Tx); GPIO_InitStructure_Rx.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure_Rx.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure_Rx.GPIO_PuPd = GPIO_PuPd_UP; GPIO_InitStructure_Rx.GPIO_Speed = GPIO_Speed_100MHz; GPIO_Init(GPIOx, &GPIO_InitStructure_Rx); USART_InitStructure.USART_BaudRate = BaudRate; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(usart_priv_obj->USARTx, &USART_InitStructure); USART_DMA_Config(); USART_ClearITPendingBit(usart_priv_obj->USARTx, USART_IT_TC);//清除传输完成 USART_ITConfig(usart_priv_obj->USARTx, USART_IT_TC, ENABLE); USART_ITConfig(usart_priv_obj->USARTx, USART_IT_IDLE, ENABLE); NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 6; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_Init(&NVIC_InitStructure); USART_Cmd(usart_priv_obj->USARTx, ENABLE); return 0; } /* *@函数名:usart_deinit *@函数功能:重置指定串口 *@参数: * @pDev:指定串口句柄 *@返回值:无 */ static void usart_deinit(usart_obj_t *pDev) { usart_priv_obj_t *usart_priv_obj = pDev->usart_priv_data; USART_DeInit(usart_priv_obj->USARTx); } /* *@函数名:usart_print *@函数功能:串口格式化发送数据 *@参数: * @pDev:指定串口句柄 * @timeout_ms:等待超时时间 * 参数值:0~portMAX_DELAY; * @format:待发送字符串 * @...:可变参数 *@返回值 * 0:串口发送成功 * -1:串口发送失败 */ static int usart_print(usart_obj_t *pDev, INT32U timeout_ms, char *format, ...) { OS_ERR err; usart_priv_obj_t *usart_priv_obj = pDev->usart_priv_data; /* 格式化字符串复制到缓冲区 */ va_list arg; va_start(arg, format); vsprintf(usart_priv_obj->SendBuffer, format, arg); va_end(arg); usart_priv_obj->pSendBuffer = usart_priv_obj->SendBuffer; /* 开启发送中断,在中断中发送数据 */ USART_ITConfig(usart_priv_obj->USARTx, USART_IT_TXE, ENABLE); /* 等待中断发送完成释放信号量 */ OSSemPend(usart_priv_obj->xSemphr_Send, timeout_ms, &err); if (err != OS_ERR_NONE) { return 0; } else { return -1; } } /* *@函数名:usart_send *@函数功能:串口发送数据 *@参数: * @pDev:指定串口句柄 * @data:待发送数据 *@返回值 * 0:串口发送成功 * -1:串口发送失败 */ static void usart_send(usart_obj_t *pDev, uint8_t *data, uint16_t dataLenght) { OS_ERR err; usart_priv_obj_t *usart_priv_obj = pDev->usart_priv_data; OSSemPend(usart_priv_obj->xSemphr_Send, 0, &err); DMA_Cmd(USART_TX_DMA_STREAM, DISABLE); USART_TX_DMA_STREAM->M0AR = (uint32_t)data; DMA_SetCurrDataCounter(USART_TX_DMA_STREAM, dataLenght);//设置需要发送的量 DMA_Cmd(USART_TX_DMA_STREAM, ENABLE); } /* *@函数名:usart_receive *@函数功能:从串口接收队列中读取一个数据 *@参数: * @pDev:指定串口句柄 * @data:保存接收到的数据 * @timeout_ms:等待超时时间 * 参数值:0~portMAX_DELAY; *@返回值 * 0:读取串口队列成功 * -1:读取串口超时 */ static int usart_receive(struct USART *pDev, uint8_t *data, uint16_t data_len, uint16_t *rec_br, INT32U timeout_ms) { OS_ERR err; usart_priv_obj_t *usart_priv_obj = pDev->usart_priv_data; /* 读取串口接收队列 */ OSSemPend(usart_priv_obj->xSemphr_Receive, timeout_ms, &err); if (err == OS_ERR_NONE) { *rec_br = Receive_Queue_Buffer_Count; Receive_Queue_Buffer_Count = 0; if(data_len > *rec_br) { data_len = (*rec_br); } memcpy(data, Receive_Queue_Buffer, data_len); return 0; } else { return -1; } } /* *@函数名:usart_wait_message_count *@函数功能:获取串口接收队列剩余数据量 *@参数: * @pDev:指定串口句柄 *@返回值:串口接收队列剩余数据量 */ static uint32_t usart_wait_message_count(usart_obj_t *pDev) { usart_priv_obj_t *usart_priv_obj = pDev->usart_priv_data; return ((OS_Q *)(usart_priv_obj->xQueue_Receive->OSEventPtr))->OSQEntries; } /* *@函数名:usart_irq_handle *@函数功能:处理串口发送和接收中断 *@参数: * @pDev:待处理中断的串口句柄 *@返回值:无 */ //UBaseType_t semaphore; static void usart_irq_handle(usart_obj_t *pDev) { OS_CPU_SR cpu_sr; OS_ENTER_CRITICAL(); OSIntEnter(); /* Tell uC/OS-III that we are starting an ISR */ OS_EXIT_CRITICAL(); usart_priv_obj_t *usart_priv_obj = pDev->usart_priv_data; /* 发送寄存器为空,填入数据到发送寄存器开始发送 */ if(SET == USART_GetITStatus(usart_priv_obj->USARTx, USART_IT_TC)) { OSSemPost(usart_priv_obj->xSemphr_Send); DMA_ClearFlag(USART_TX_DMA_STREAM, DMA_FLAG_TCIF7); //清除DMA传输完成标志 DMA_ClearFlag(USART_TX_DMA_STREAM, DMA_FLAG_HTIF7); //清除DMA传输完成标志 USART_ClearITPendingBit(usart_priv_obj->USARTx, USART_IT_TC); //清除传输完成 } /* 空闲中断接收到完整的数据帧 */ if(SET == USART_GetITStatus(usart_priv_obj->USARTx, USART_IT_IDLE)) { OSSemPost(usart_priv_obj->xSemphr_Receive); /* 清除计数器和空闲中断标志位 */ USART_GetITStatus(usart_priv_obj->USARTx, USART_IT_IDLE); USART_ReceiveData(usart_priv_obj->USARTx); Receive_Queue_Buffer_Count = Receive_Queue_Max_Length - DMA_GetCurrDataCounter(USART_RX_DMA_STREAM); DMA_ClearFlag(USART_RX_DMA_STREAM, DMA_FLAG_TCIF5); //清除DMA传输完成标志 DMA_ClearFlag(USART_RX_DMA_STREAM, DMA_FLAG_HTIF5); //清除DMA传输完成标志 DMA_Cmd(USART_RX_DMA_STREAM, DISABLE); DMA_SetCurrDataCounter(USART_RX_DMA_STREAM, Receive_Queue_Max_Length);//设置需要接收的量 DMA_Cmd(USART_RX_DMA_STREAM, ENABLE); } OSIntExit(); } /* *@函数名:USART1_IRQHandler *@函数功能:处理串口1发送和接收中断 *@参数:无 *@返回值:无 */ void USART1_IRQHandler(void) { usart_irq_handle(&g_usart1); } /* *@函数名:USART2_IRQHandler *@函数功能:处理串口2发送和接收中断 *@参数:无 *@返回值:无 */ void USART2_IRQHandler(void) { usart_irq_handle(&g_usart2); } /* *@函数名:USART3_IRQHandler *@函数功能:处理串口3发送和接收中断 *@参数:无 *@返回值:无 */ void USART3_IRQHandler(void) { usart_irq_handle(&g_usart3); } #if (USE_STM32F103_Cxxx != 1) /* *@函数名:UART4_IRQHandler *@函数功能:处理串口4发送和接收中断 *@参数:无 *@返回值:无 */ void UART4_IRQHandler(void) { usart_irq_handle(&g_uart4); } /* *@函数名:UART5_IRQHandler *@函数功能:处理串口5发送和接收中断 *@参数:无 *@返回值:无 */ void UART5_IRQHandler(void) { usart_irq_handle(&g_uart5); } #endif /* *@函数名:Get_USART_Handle *@函数功能:获取指定串口句柄 *@参数: * @name:串口名称 *@返回值:串口句柄 */ usart_obj_t *get_usart_obj(char *name) { uint8_t usart_dev_num = sizeof(g_usart_devs) / sizeof(g_usart_devs[0]); for(uint8_t i = 0; i < usart_dev_num; i++) { if(0 == strcmp(name, g_usart_devs[i]->name)) { return g_usart_devs[i]; } } return NULL; } static void USART_DMA_Config(void) { DMA_InitTypeDef DMA_InitStructure; RCC_AHB1PeriphClockCmd(USART_TX_DMA_CLK | USART_RX_DMA_CLK, ENABLE);//使能DMA2时钟 /* 配置发送 */ DMA_InitStructure.DMA_BufferSize = 0;//随便配置,因为在接收到数据后我们会重新给这值赋值 DMA_InitStructure.DMA_Channel = USART_TX_DMA_CHANNEL;//串口发送通道 DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;//DMA搬运方向:存储器到外设 DMA_InitStructure.DMA_Memory0BaseAddr = 0;//存储器地址 DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//存储器突发模式选择:单次模式 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//存储器数据宽度:字节 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable ;//使能存储器地址自动递增功能 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;//DMA 传输模式选择:一次传输 DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR;//外设地址 DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//外设突发模式选择:单次模式 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据宽度:字节 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//禁止外设地址自动递增功能 DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//软件设置数据流的优先级:中等 /* FIFO不用随便配置 */ DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; DMA_Init(USART_TX_DMA_STREAM, &DMA_InitStructure); DMA_Cmd(USART_TX_DMA_STREAM, DISABLE);//发送先失能 /* 配置接收 */ DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)Receive_Queue_Buffer;//存储器地址 DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR;//外设地址 DMA_InitStructure.DMA_BufferSize = Receive_Queue_Max_Length;//接收数据的长度 DMA_InitStructure.DMA_Channel = USART_RX_DMA_CHANNEL;//串口接收通道 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;//DMA搬运方向:外设到存储器 DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//DMA 传输模式选择:循环接收 /* 其余配置与上面一样 */ DMA_Init(USART_RX_DMA_STREAM, &DMA_InitStructure); DMA_ClearFlag(USART_RX_DMA_STREAM, DMA_FLAG_TCIF5); //清除DMA传输完成标志 DMA_ClearFlag(USART_RX_DMA_STREAM, DMA_FLAG_HTIF5); //清除DMA传输完成标志 DMA_Cmd(USART_RX_DMA_STREAM, DISABLE);//发送先失能 DMA_Cmd(USART_RX_DMA_STREAM, ENABLE);//接收使能 USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE); USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE); }