本帖最后由 zero949079783 于 2024-2-18 22:26 编辑
STM32F429 LVGL(8.3)+FreeRTOS(FreeRTOS V10.4.6)+软件分层设计
GD32F427 LVGL(8.3)+FreeRTOS(FreeRTOS V10.4.6)+软件分层设计
应用层:主要编写应用方面的,如功能实现等,实现的串口收发(演示),驱动层:各种外设软件层,应用层与驱动分离方式使用指针函数和回调函数分开
标准库层:仅STM32标准库或GD32库
中间层:LVGL,FreeRTOS,同理也软件与驱动分层。 使用systick定时器作为时钟节拍。
每一层都使函数指针
- // 函数指针变量,保存任务调度的函数地址
- void (*usartTakeFunCb)(uint8_t *data,uint16_t datalen);
- /**
- ***********************************************************
- * [url=home.php?mod=space&uid=247401]@brief[/url] 注册任务调度回调函数
- * @param pFunc, 传入回调函数地址
- * [url=home.php?mod=space&uid=266161]@return[/url]
- ***********************************************************
- */
- void usart1TakeCb(void(*pFunc)(uint8_t *data,uint16_t datalen))
- {
- usartTakeFunCb = pFunc;
- }
应用层:实现的串口收发(演示)
发送接收缓冲区大小:2048
单次接收最大量:256
串口接收:DMA+空闲中断+双指针+双环形缓冲区
串口发送:DMA+发送中断+双指针+双环形缓冲区
- #define UARTx_RX_SIZE 2048 //接收缓冲区长度
- #define UARTx_TX_SIZE 2048 //发送缓冲区长度
- #define UARTx_RX_MAX 256 //单次接收最大量
- #define UARTx_TX_MAX 256 //单次接收最大量
- #define SE_PTR_NUM 10 //se指针对结构体数组长度
- typedef struct{
- uint8_t *start; //start用于标记起始位置
- uint8_t *end; //end用于标记结束位置
- }LCB; //se 指针对结构体
- typedef struct{
-
-
- uint16_t RxCounter; //累计接收数据量
- uint16_t TxCounter;
- uint16_t TxState;
- LCB RxLocation[SE_PTR_NUM]; //se指针对结构体数组
- LCB *RxInPtr; //IN指针用于标记接收数据
- LCB *RxOutPtr; //OUT指针用于提取接收的数据
- LCB *RxEndPtr; ////IN和OUT指针的结尾标志
-
- LCB TxLocation[SE_PTR_NUM]; //se指针对结构体数组
- LCB *TxInPtr; //IN指针用于标记发送数据
- LCB *TxOutPtr; //OUT指针用于提取发送的数据
- LCB *TxEndPtr; ////IN和OUT指针的结尾标志
- USART_InitTypeDef usart;
- DMA_InitTypeDef dmatx;
- DMA_InitTypeDef dmarx;
-
- }Usartx_Control_Block;
- extern uint8_t Usart1_RxBuffer[UARTx_RX_SIZE]; //串口1接收缓冲区
- extern uint8_t Usart1_TxBuffer[UARTx_TX_SIZE]; //串口1发送缓冲区
- extern Usartx_Control_Block usart1; //串口控制结构体
串口驱动层接收:
- void USART1_IRQHandler(void)
- {
- //发送中断
- if(USART_GetITStatus(USART1,USART_IT_TC) != RESET)
- {
- USART_ClearITPendingBit(USART1,USART_IT_TC);
- }
- //空闲中断
- if(USART_GetITStatus(USART1,USART_IT_IDLE) != RESET)
- {
- USART1->SR; //清中断
- USART1->DR; //清中断
- usart1.RxCounter +=((UARTx_RX_MAX+1)- DMA_GetCurrDataCounter(DMA2_Stream2));
- usart1.RxInPtr->end = &Usart1_RxBuffer[usart1.RxCounter - 1];
-
- usart1.RxInPtr++;
- if(usart1.RxInPtr == usart1.RxEndPtr)
- {
- usart1.RxInPtr = &usart1.RxLocation[0];
- }
- if(UARTx_RX_SIZE - usart1.RxCounter < UARTx_RX_MAX){
- usart1.RxInPtr->start = Usart1_RxBuffer;
- usart1.RxCounter = 0;
- }else{
- usart1.RxInPtr->start = &Usart1_RxBuffer[usart1.RxCounter]; //标记接位置
- }
-
- DMA_Cmd(DMA2_Stream2, DISABLE); //关闭DMA
- DMA_SetCurrDataCounter(DMA2_Stream2, UARTx_RX_MAX+1);
- DMA2_Stream2->M0AR = (uint32_t)usart1.RxInPtr->start;
- DMA_Cmd(DMA2_Stream2, ENABLE); //打开DMA
- }
- }
串口驱动层发送:
- void Usart1_Txdata(uint8_t *tdata,uint16_t datalen)
- {
-
- if((UARTx_TX_SIZE - usart1.TxCounter) >= datalen) //发送空间大于等于发数据
- {
- usart1.TxInPtr ->start = &Usart1_TxBuffer[usart1.TxCounter];
- }else
- {
- usart1.TxCounter = 0; //发送空间小于发送数据,清0
- usart1.TxInPtr->start = Usart1_TxBuffer;
- }
-
- memcpy(usart1.TxInPtr ->start,tdata,datalen); //数据拷贝
- while (DMA_GetCmdStatus(DMA2_Stream7) != DISABLE); //确保DMA可以被设置
- DMA_SetCurrDataCounter(DMA2_Stream7,datalen); //设置数据传输长度
-
- usart1.TxCounter += datalen; //统计每次发送量
- usart1.TxInPtr ->end = &Usart1_TxBuffer[usart1.TxCounter-1];//标记end位,为下次作准备
- DMA2_Stream7->M0AR = (uint32_t)usart1.TxInPtr->start;
- DMA_SetCurrDataCounter(DMA2_Stream7, UARTx_TX_MAX);
- usart1.TxInPtr++;
- if(usart1.TxInPtr == usart1.TxEndPtr){
- usart1.TxInPtr = &usart1.TxLocation[0];
- }
- }
- void Usart1_Event(uint8_t *data,uint16_t datalen)//任务事件入口
- {
- Usart1_Txdata(data,datalen);
- }
- void Usart1_Taskapp(void)
- {
- usart1TakeCb(Usart1_Event);//任务事件回函数入口地址
- }
串口任务函数:
|