stm32---dma串口發送+fifo隊列框架

之前分享了一個關于gd32的fifo框架,這次就用stm32仿照寫一個,其實幾乎一樣,這次說的更詳細點,我全文都寫上了注釋,大家直接cv模仿我的調用方式即可

uasrt.c

#include "stm32f10x.h"                  // Device header
#include "queue.h"void myDMA_init(void);
void myNVIC_Config(void);queue_t  uart1_queue_in,uart1_queue_out ;  //定義2個結構體變量,分別是入、出棧
uint8_t recv_buf[256] = {0};  			   //接收緩沖區大小256  byte
static uint8_t send_buf[256] = {0};        //發送緩沖區大小256  byte
static uint8_t usart1_tx_buf[64];
static uint8_t uart1_send_ready = 1;void uart1_queue_init(void)
{queue_init(&uart1_queue_in,recv_buf,sizeof(recv_buf));//初始化壓棧的緩沖區queue_init(&uart1_queue_out,send_buf,256);		      //初始化出棧的緩沖區
}
/* **************************************************************************************
*	函 數 名: uart_get_queue_data
*	功能說明: 拿取uart in隊列的數據
*	形    參: p_buf : 數據存儲地址
*			size : 拿取個數
*	返 回 值: 無
*   備    注: 無
*****************************************************************************************/
uint16_t uart1_get_queue_data(uint8_t * p_buf,uint16_t size)
{return queue_out_data(&uart1_queue_in,p_buf,size);
}/* **************************************************************************************
*	函 數 名: uart_get_data_len
*	功能說明: 返回uart in 隊列的儲存數據長度
*	形    參: 無
*			
*	返 回 值: 數據長度
*   備    注: 無
*****************************************************************************************/
uint16_t uart1_get_data_len(void)
{return queue_get_num(&uart1_queue_in);
}/* **************************************************************************************
*	函 數 名: uart_put_queue_data
*	功能說明: 把數據壓進uart out隊列
*	形    參: p_buf : 數據存儲地址
*				size : 壓的個數
*	返 回 值: 無
*   備    注: 無
*****************************************************************************************/
uint16_t uart1_put_queue_data(uint8_t * p_buf,uint16_t size)
{return queue_in_data(&uart1_queue_out,p_buf,size);
}/* **************************************************************************************
*	函 數 名: uart_send_poll
*	功能說明: 輪詢uart out 隊列并通過dma發送
*	形    參: 
*			
*	返 回 值: 發送數據個數
*   備    注: 無
*****************************************************************************************/
uint8_t uart0_send_poll(void)
{uint8_t n = 0;	if(uart1_send_ready)//串口tx緩沖區是否有數據并傳輸完成?{n = queue_out_data(&uart1_queue_out,usart1_tx_buf,sizeof(usart1_tx_buf));	//計算大小if(n){uart1_send_ready=0;DMA_Cmd(DMA1_Channel4,DISABLE);DMA_SetCurrDataCounter(DMA1_Channel4,n);DMA_Cmd(DMA1_Channel4,ENABLE);return n;}}return 0;
}void USART1_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);USART_InitTypeDef USART_InitStructure;USART_InitStructure.USART_BaudRate = 115200;USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;USART_InitStructure.USART_Parity = USART_Parity_No;USART_InitStructure.USART_StopBits = USART_StopBits_1;USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_Init(USART1, &USART_InitStructure);USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;NVIC_Init(&NVIC_InitStructure);USART_Cmd(USART1, ENABLE);USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE); // 使能USART1的DMA發送請求(關鍵!)myDMA_init();myNVIC_Config();uart1_queue_init();	
}void myDMA_init(void)
{	DMA_InitTypeDef DMA_InitStructure;// 使能DMA1時鐘RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);// 配置DMA1通道4(USART1_TX)DMA_DeInit(DMA1_Channel4);  // 復位DMA通道4到默認值DMA_InitStructure.DMA_PeripheralBaseAddr 	= (uint32_t)&USART1->DR;  			 // 外設基址:USART1數據寄存器DMA_InitStructure.DMA_MemoryBaseAddr 		= (uint32_t)usart1_tx_buf;           // 內存基址:發送緩沖區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; // 外設數據寬度8位DMA_InitStructure.DMA_MemoryDataSize 		= DMA_MemoryDataSize_Byte;     // 內存數據寬度8位DMA_InitStructure.DMA_Mode 					= DMA_Mode_Normal;                       // 普通模式(非循環)DMA_InitStructure.DMA_Priority 				= DMA_Priority_High;               // 中等優先級DMA_InitStructure.DMA_M2M					= DMA_M2M_Disable;                        // 非內存到內存模式DMA_Init(DMA1_Channel4, &DMA_InitStructure);// 使能DMA1通道4傳輸完成中斷DMA_ITConfig(DMA1_Channel4, DMA_IT_TE, ENABLE);	
}void myNVIC_Config(void)
{NVIC_InitTypeDef NVIC_InitStructure;// 配置DMA1_Channel4_IRQn的中斷優先級NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  // 搶占優先級1NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;         // 子優先級1NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);
}void USART1_IRQHandler(void)
{uint8_t Res;if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET){Res = USART_ReceiveData(USART1);//接收到的數據進行入棧,壓棧queue_in_data(&uart1_queue_in,&Res,1);USART_ClearITPendingBit(USART1, USART_IT_RXNE);}
}
void DMA1_Channel4_IRQHandler(void)
{if (DMA_GetITStatus(DMA1_IT_TC4) != RESET) // 檢查DMA1通道4傳輸完成中斷標志{		uart1_send_ready  = 1;DMA_ClearITPendingBit(DMA1_IT_TC4); // 清除中斷標志}
}

queue.c

#include "queue.h"/*** @brief  Initialize the circular queue* @param  queue: Queue* @param  buffer: Queue's buffer* @param  size: buff size* @retval None*/
void queue_init(queue_t *queue,uint8_t *buffer, uint16_t size)
{queue->buffer = buffer;queue->size = size;queue->head = 0;queue->tail = 0;queue->length = 0;queue->GetLen = 0;queue->PutLen = 0;
}/*** @brief  Insert element into the circular queue* @param  queue: Queue* @param  buffer: Queue's buffer* @param  count: element length* @retval Number of elements inserted successfully*/
uint16_t queue_in_data(queue_t *queue, const uint8_t *buffer, uint16_t count)  //Zhixing Change 250430
{uint16_t i = 0;for(i=0; i<count; i++){if(queue->GetLen == 0){if(queue->PutLen == (queue->size - 1)) return i; }else{if(queue->PutLen == (queue->GetLen - 1)) return i;  }queue->buffer[queue->PutLen++] = *buffer++;queue->PutLen %= queue->size;}return i;
}/*** @brief  Delete element from the circular queue* @param  queue: Queue* @param  buffer: Queue's buffer* @param  count: element length* @retval Number of elements deleted successfully*/
uint16_t queue_out_data(queue_t *queue,uint8_t *buffer, uint16_t count)  //Zhixing Change 250430
{uint16_t i = 0;//__disable_irq();for(i=0; i<count; i++){/*if(queue->length == 0)//empty{__enable_irq();return i;}*/if(queue->PutLen == queue->GetLen) return i;*buffer++ = queue->buffer[queue->GetLen++];if(queue->GetLen == queue->size) queue->GetLen = 0;}//__enable_irq();return i;
}/*** @brief  Get the remaining amount of data length from queue* @param  queue: Queue* @retval data length*/
uint16_t queue_get_num(queue_t *queue)
{return queue->length;
}/******************** (C)Copyright MidiPlus Software ********************/

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/83602.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/83602.shtml
英文地址,請注明出處:http://en.pswp.cn/web/83602.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【生產就曲篇】讓應用可觀測:Actuator監控端點與日志最佳實踐

摘要 本文是《Spring Boot 實戰派》系列的終章&#xff0c;我們將探討如何讓應用真正達到**“生產就緒” (Production-Ready)** 的標準。文章的核心是可觀測性 (Observability)&#xff0c;即從外部了解一個系統內部運行狀態的能力。 我們將深度挖掘 Spring Boot Actuator 的…

操作系統知識(1)

操作系統的分類總結 1、批處理操作系統:單道批處理和多道批處理(主機與外設可并行) 2、分時操作系統:一個計算機系統與多個終端設備連接。將CPU的工作時間劃分為許多很短的時間片&#xff0c;輪流為各個終端的用戶服務。 3、實時操作系統:實時是指計算機對于外來信息能夠以足…

一.Sharding分庫分表-基因法+自定義多key分片實現多字段查詢

前言 當下遇到這樣一個場景&#xff0c;由于訂單數據量達到千萬級別&#xff0c;采用分庫分表進行優化&#xff0c;根據訂單的熱查條件&#xff1a;order_no訂單編號進行分表&#xff0c;但是這樣帶來一個問題&#xff0c;用戶查詢自己的訂單怎么查&#xff1f;由于分片鍵使用…

【leetcode】543. 二叉樹的直徑

二叉樹的直徑 題目題解解釋 題目 543. 二叉樹的直徑 給你一棵二叉樹的根節點&#xff0c;返回該樹的 直徑 。 二叉樹的 直徑 是指樹中任意兩個節點之間最長路徑的 長度 。這條路徑可能經過也可能不經過根節點 root 。 兩節點之間路徑的 長度 由它們之間邊數表示。 題解 …

AI基礎知識(07):基于 PyTorch 的手寫體識別案例手冊

目錄 實驗介紹 實驗對象 實驗時間 實驗流程 實驗介紹 隨著人工智能技術的飛速發展&#xff0c;圖像識別技術在眾多領域得到了廣泛應用。手寫體識別作為圖像 識別的一個重要分支&#xff0c;其在教育、金融、醫療等領域具有廣泛的應用前景。本實驗旨在利用深度 學習框架 PyTorc…

wordpress后臺更新后 前端沒變化的解決方法

使用siteground主機的wordpress網站&#xff0c;會出現更新了網站內容和修改了php模板文件、js文件、css文件、圖片文件后&#xff0c;網站沒有變化的情況。 不熟悉siteground主機的新手&#xff0c;遇到這個問題&#xff0c;就很抓狂&#xff0c;明明是哪都沒操作錯誤&#x…

信號(瞬時)頻率求解與仿真實踐(2)

引言 本文是信號(瞬時)頻率求解與仿真實踐專題的第二篇文章&#xff0c;在上一篇博文 [1]信號(瞬時)頻率求解與仿真實踐(1)-CSDN博客中&#xff0c;我構建了信號瞬時頻率求解的基本框架&#xff0c;并且比較詳細地討論了瞬時頻率法。這篇博文探討適用于信號瞬時頻率求解的另一種…

Linux運行發布jar文件攜帶哪些參數

在 CentOS 8 上運行發布的 JAR 文件時,可以根據不同需求攜帶以下參數: 1. 基本運行方式 bash 復制 下載 java -jar your-application.jar 2. 常用 JVM 參數 參數說明-Xms256m初始堆內存大小(如 256MB)-Xmx1024m最大堆內存大小(如 1GB)-XX:MaxMetaspaceSize=256m元空間…

在GIS 工作流中實現數據處理(4)

結果輸出與可視化 最后&#xff0c;我們將統計結果輸出為一個 Excel 文件&#xff0c;并在 ArcMap 中對城市中心區域的土地利用情況進行可視化展示。 import pandas as pd# 將統計表格轉換為 pandas DataFrame df pd.read_csv(statistics_table, sep"\t")# 輸出為…

【術語解釋】網絡安全((SAST, DAST, SCA, IAST),Hadoop, Spark, Hive 的關系

## OWASP Top 10等 OWASP Top 10&#xff1a;OWASP (Open Worldwide Application Security Project&#xff0c;開放全球應用程序安全項目) Top 10 是一份由全球安全專家定期更新的報告&#xff0c;列出了當前 Web 應用程序面臨的十大最關鍵安全風險。 它是一個廣受認可的意識文…

NY197NY205美光閃存固態NY218NY226

NY197NY205美光閃存固態NY218NY226 美光科技作為全球領先的半導體存儲解決方案供應商&#xff0c;其閃存固態硬盤&#xff08;SSD&#xff09;產品線一直備受業界關注。NY197、NY205、NY218和NY226是美光近期推出的幾款重要固態硬盤型號&#xff0c;它們在性能、容量和適用場景…

MinHook 對.NET底層的 SendMessage 攔截真實案例反思

一&#xff1a;背景 1. 講故事 上一篇我們說到了 minhook 的一個簡單使用&#xff0c;這一篇給大家分享一個 minhook 在 dump 分析中的實戰&#xff0c;先看下面的線程棧。 0:044> ~~[138c]s win32u!NtUserMessageCall0x14: 00007ffc5c891184 c3 ret 0:061&g…

qt配合海康工業相機取圖開發

1.最近開發海康工業相機&#xff0c;做取圖demo 2.在MVS運行目錄下找到Development文件夾&#xff0c;找到下圖兩個文件夾一個是頭文件一個是庫文件 3.引用到qt項目中 4.下面是頭文件跟源文件 頭文件 #ifndef MVSCAMERA_H #define MVSCAMERA_H#include <QObject> #incl…

JavaScript基礎學習與應用(后端了解部分)

JavaScript JavaScript原名liveScrip,由美國網景公司開發的一種用于對網頁操作的腳本語言 腳本語言:(不需要編譯 sql html css)由某種解釋器直接解釋運行的 JavaScript是一種解釋性的腳本語言 JavaScript是網頁的行為,可以為網頁提供各種行為(圖片操作) JavaScript一般一對…

Linux環境下安裝和使用RAPIDS平臺的cudf和cuml - pip 安裝方法

? cuDF 和 cuML 是 RAPIDS平臺 的兩個核心組件&#xff0c;它們共同構成了RAPIDS平臺的主要功能 1.linux環境下pip安裝 pip install cuml-cu1224.6.0 --extra-index-urlhttps://pypi.nvidia.com 安裝過程中可能會提示缺少包之類的&#xff0c;按提示進行包的缺失安裝 2.安裝…

基于 Redis 的冪等性設計:SpringBoot @Async 在高并發 MySQL 日志存儲中的應用

一、問題描述 在高并發場景下,大量設備實時上報狀態數據,需要異步保存到MySQL,同時需要解決冪等性校驗和線程池耗盡問題。 二、解決方案 1. 冪等性控制 作用:確保同一請求無論執行多少次,結果都一致,避免重復處理。 實現方式: 唯一標識:設備ID + 時間戳組合Redis原…

ELK日志采集系統

ELK 日志采集系統指的是由 Elasticsearch、Logstash 和 Kibana 三個核心開源軟件組成的套件&#xff0c;用于集中式日志的采集、處理、存儲、搜索、分析和可視化。它現在更常被稱為 Elastic Stack&#xff0c;因為其組件生態已經擴展&#xff08;尤其是引入了 Beats&#xff09…

什么是音頻?

引言&#xff1a;聲音的本質 什么是音頻&#xff1f;振動與感知 音頻&#xff0c;在其最核心的層面&#xff0c;即是我們通常所說的聲音。它起源于物體的振動。這些振動擾動了其周圍的介質&#xff08;例如空氣或水&#xff09;&#xff0c;在介質中產生了微小的壓力變化&…

接口 RESTful 中的超媒體:REST 架構的靈魂驅動

在 RESTful 架構中&#xff0c;** 超媒體&#xff08;Hypermedia&#xff09;** 是一個核心概念&#xff0c;它體現了 REST 的 “表述性狀態轉移&#xff08;Representational State Transfer&#xff09;” 的本質&#xff0c;也是區分 “真 RESTful API” 與 “偽 RESTful AP…

centos clamav 掃描及告警配置

centos clamav 掃描及告警配置 1 下載1.1官網下載1.2 在線下載2 配置3 掃描3.1 更新病毒庫3.2 掃描4 告警4.1 安裝 Postfix4.2 安裝mail郵件工具4.3 配置4.4 發送告警郵箱信息5 定時配置(cronie)5.1 定時更新病毒庫5.2 定時掃描1 下載 1.1官網下載 官網下載地址,下載rpm包…