日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

串口驱动设计

發布時間:2025/4/5 编程问答 15 豆豆
生活随笔 收集整理的這篇文章主要介紹了 串口驱动设计 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

    • 1 串口驅動設計

1 串口驅動設計

串口發送或者接收,各自實現了一個"管道"。對于任意管道,一端寫入數據,另一端讀取數據。或者可以理解為一方生產,一方消費,即所謂的"生產-消費者模型"。

以串口數據發送為例,該驅動完成任務與發送中斷之間的通信。

通信通過自定義的全局數據結構來實現,待發送的數據寫入到循環FIFO中。然后結合信號量來實現讀寫的同步,使用開關中斷來對全局數據的訪問進行共享保護控制。

串口數據的接收,工作原理和發送類似。

可以看到,無論是發送還是接受,通過RTOS的這些功能模塊能夠有效地提升數據收發效率。

實現代碼如下:
uart.h:

/*** @brief 串口驅動* @details* @author 01課堂 李述銅 http://01ketang.cc* @date 2017-06-01* @version 1.0* @copyright 版權所有,禁止用于商業用途*/ #ifndef UART_H #define UART_H#define UART_BAUDRATE 115200 #define UART_RXBUFFER_SIZE 32 #define UART_TXBUFFER_SIZE 128void UartInit (void); void UartRead (char * packet, uint32_t len); void UartWrite (const char * packet, uint32_t len);#endif //UART_H

uart.c:

/*** @brief 串口驅動* @details* @author 01課堂 李述銅 http://01ketang.cc* @date 2017-06-01* @version 1.0* @copyright 版權所有,禁止用于商業用途*/ #include "tinyOS.h" #include "uart.h" #include "stm32f10x_usart.h"static uint8_t rxBuffer[UART_RXBUFFER_SIZE]; static uint32_t rxWritePos; static uint32_t rxReadPos; static tSem rxReceivedSem;static uint8_t txBuffer[UART_TXBUFFER_SIZE]; static uint32_t txWritePos; static uint32_t txReadPos; static tSem txFreeSem;/*** 中斷處理函數*/ void USART1_IRQHandler (void) {ITStatus status;// 串口接收status = USART_GetITStatus(USART1, USART_IT_RXNE);if (status == SET) {tSemInfo semInfo;uint16_t ch = (uint32_t)USART_ReceiveData(USART1);// 僅當有空閑空間時才寫入,否則丟棄tSemGetInfo(&rxReceivedSem, &semInfo);if (semInfo.count < semInfo.maxCount) {tTaskCritical_t critical = tTaskEnterCritical();rxBuffer[rxWritePos++] = (uint8_t)ch;if (rxWritePos >= UART_RXBUFFER_SIZE) {rxWritePos = 0;}tTaskExitCritical(critical);tSemNotify(&rxReceivedSem);}USART_ClearITPendingBit(USART1, USART_IT_RXNE);}// 發送中斷: 自動從郵箱中取數據發送status = USART_GetITStatus(USART1, USART_IT_TXE);if (status == SET) {tSemInfo semInfo;// 如果發送緩沖有數據,取一個發送tSemGetInfo(&txFreeSem, &semInfo);if (semInfo.count < semInfo.maxCount) {tTaskCritical_t critical;uint8_t ch;// 從發送緩沖區中取數據critical = tTaskEnterCritical();ch = txBuffer[txReadPos++];if (txReadPos >= UART_TXBUFFER_SIZE) {txReadPos = 0;}tTaskExitCritical(critical);tSemNotify(&txFreeSem);USART_SendData(USART1, (uint16_t)ch);} else {USART_ITConfig(USART1, USART_IT_TXE, DISABLE);}USART_ClearITPendingBit(USART1, USART_IT_TXE); } }/*** USART硬件初始化*/ static void UartHalInit (void) {USART_InitTypeDef USART_InitStructure;GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_Init(GPIOA, &GPIO_InitStructure);USART_InitStructure.USART_BaudRate = UART_BAUDRATE;USART_InitStructure.USART_WordLength = USART_WordLength_9b;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);USART_Cmd(USART1, ENABLE);USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);NVIC_EnableIRQ(USART1_IRQn); }/*** 初始化串口*/ void UartInit (void) {UartHalInit();tSemInit(&rxReceivedSem, 0, UART_RXBUFFER_SIZE);rxReadPos = 0;rxWritePos = 0;tSemInit(&txFreeSem, UART_TXBUFFER_SIZE, UART_TXBUFFER_SIZE);txReadPos = 0;txWritePos = 0;}/*** 等待接收數據包* @param packet 接收到的數據包指針存儲地址* @return 0 無錯誤;1 有錯誤*/ void UartRead (char * packet, uint32_t len) {tTaskCritical_t critical;while (len -- > 0) {tSemWait(&rxReceivedSem, 0);// 從接收緩沖區中讀取critical = tTaskEnterCritical();*packet++ = rxBuffer[rxReadPos++];if (rxReadPos >= UART_RXBUFFER_SIZE) {rxReadPos = 0;}tTaskExitCritical(critical);} }/*** 寫入數據包* @param packet 待寫入的數據包*/ void UartWrite (const char * packet, uint32_t len) {tTaskCritical_t critical;uint32_t status;while (len-- > 0) {// 等待空閑空間tSemWait(&txFreeSem, 0);// 寫入發送緩沖區critical = tTaskEnterCritical();txBuffer[txWritePos++] = *packet++;if (txWritePos >= UART_TXBUFFER_SIZE) {txWritePos = 0;}tTaskExitCritical(critical);// 這里加循環反復調用,是考慮到中途可能發生其它中斷延遲導致沒有及時觸發// 只有當硬件真正在空閑時,才手動觸發一次status = USART_GetFlagStatus(USART1, USART_FLAG_TXE);if (status == SET) {USART_ITConfig(USART1, USART_IT_TXE, ENABLE);}} }

app.c:

/*** @brief tOS應用示例* @details* @author 01課堂 李述銅 http://01ketang.cc* @date 2017-06-01* @version 1.0* @copyright 版權所有,禁止用于商業用途*/ #include "tinyOS.h" #include "app.h" #include "hal.h"#include "button.h" #include "uart.h"static tTaskStack task1Env[TASK1_ENV_SIZE]; // 任務1的堆棧空間 static tTask task1;void task1Entry (void * param) {char str[64];uint32_t count = 0;for (;;) { // sprintf(str, "Button press: %d\n", count++); // UartWritePacket(str);char msg;UartRead(&msg, 1);UartWrite(&msg, 1);} }/*** App的初始化*/ void tInitApp (void) {halInit();ButtonInit();UartInit();tTaskInit(&task1, task1Entry, (void *) 0x0, TASK1_PRIO, task1Env, sizeof(task1Env)); }

參考資料:

  • 手把手教你學用嵌入式操作系統
  • 總結

    以上是生活随笔為你收集整理的串口驱动设计的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。