日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁 > 單片機(jī) > 單片機(jī)
[導(dǎo)讀]這次講講利用串口收發(fā)中斷來進(jìn)行串口通訊。STM32 上為每個(gè)串口分配了一個(gè)中斷。也就是說無論是發(fā)送完成還是收到數(shù)據(jù)或是數(shù)據(jù)溢出都產(chǎn)生同一個(gè)中斷。程序需在中斷處理函數(shù)中讀取狀態(tài)寄存器(USART_SR)來判斷當(dāng)前的是什

這次講講利用串口收發(fā)中斷來進(jìn)行串口通訊。STM32 上為每個(gè)串口分配了一個(gè)中斷。也就是說無論是發(fā)送完成還是收到數(shù)據(jù)或是數(shù)據(jù)溢出都產(chǎn)生同一個(gè)中斷。程序需在中斷處理函數(shù)中讀取狀態(tài)寄存器(USART_SR)來判斷當(dāng)前的是什么中斷。下面的中斷映像圖給出了這些中斷源是如何匯合成最終的中斷信號(hào)的。圖中也給出了如何控制每一個(gè)單獨(dú)的中斷源是否起作用。

另外,Cortex-M3內(nèi)核中還有個(gè)NVIC,可以控制這里的中斷信號(hào)是否觸發(fā)中斷處理函數(shù)的執(zhí)行,還有這些外部中斷的級(jí)別。關(guān)于NVIC可以參考《ARM CortexM3權(quán)威指南》,里面講解的非常詳細(xì)。

簡(jiǎn)單的說,為了開啟中斷,我們需要如下的代碼:


NVIC_InitTypeDef NVIC_InitStructure;

NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//開啟接收中斷

USART_ITConfig(USART1, USART_IT_TXE, ENABLE);// 開啟發(fā)送中斷

這里多說一句,串口的發(fā)送中斷有兩個(gè),分別是:

l發(fā)送數(shù)據(jù)寄存器空中斷(TXE)

l發(fā)送完成中斷(TC)

一般來說我們會(huì)使用發(fā)送數(shù)據(jù)寄存器空中斷,用這個(gè)中斷發(fā)送的效率會(huì)高一些。

中斷處理函數(shù)的框架如下,如果檢測(cè)到錯(cuò)誤就清除錯(cuò)誤,收到數(shù)了就處理。發(fā)完當(dāng)前數(shù)據(jù)了就發(fā)下一個(gè)。


voidUSART1_IRQHandler(void)

{

unsignedintdata;

if(USART1->SR & 0x0F)

{

// See if we have some kind of error, Clear interrupt

data = USART1->DR;

}

elseif(USART1->SR & USART_FLAG_RXNE)//Receive Data Reg Full Flag

{

data = USART1->DR;

// 對(duì)收到的數(shù)據(jù)進(jìn)行處理,或者干些其他的事

}

elseif(USART1->SR & USART_FLAG_TXE)

{

{// 可以發(fā)送數(shù)據(jù)了,如果沒有數(shù)據(jù)需要發(fā)送,就在這里關(guān)閉發(fā)送中斷

USART1->DR = something;// Yes, Send character

}

}

}


下面給一個(gè)利用環(huán)形緩沖區(qū)的串口驅(qū)動(dòng)程序。


#ifndef _COM_BUFFERED_H_

#define _COM_BUFFERED_H_

#define COM1 0

#define COM2 1

#define COM_RX_BUF_SIZE 64

#define COM_TX_BUF_SIZE 64

#define COM_NO_ERR 0

#define COM_BAD_CH 1

#define COM_RX_EMPTY 2

#define COM_TX_FULL 3

#define COM_TX_EMPTY 4

unsignedcharCOMGetCharB (unsignedcharch, unsignedchar*err);

unsignedcharCOMPutCharB (unsignedcharport, unsignedcharc);

voidCOMBufferInit (void);

unsignedcharCOMBufferIsEmpty (unsignedcharport);

unsignedcharCOMBufferIsFull (unsignedcharport);

#endif



#include "stm32f10x_usart.h"

#include "com_buffered.h"

#define OS_ENTER_CRITICAL() __set_PRIMASK(1)

#define OS_EXIT_CRITICAL() __set_PRIMASK(0)

staticvoidCOMEnableTxInt(unsignedcharport)

{

staticUSART_TypeDef* map[2] = {USART1, USART2};

USART_ITConfig(map[port], USART_IT_TXE, ENABLE);

}

typedefstruct{

shortRingBufRxCtr;

unsignedchar*RingBufRxInPtr;

unsignedchar*RingBufRxOutPtr;

unsignedcharRingBufRx[COM_RX_BUF_SIZE];

shortRingBufTxCtr;

unsignedchar*RingBufTxInPtr;

unsignedchar*RingBufTxOutPtr;

unsignedcharRingBufTx[COM_TX_BUF_SIZE];

} COM_RING_BUF;

COM_RING_BUF COM1Buf;

COM_RING_BUF COM2Buf;

unsignedcharCOMGetCharB (unsignedcharport, unsignedchar*err)

{

// unsigned char cpu_sr;

unsignedcharc;

COM_RING_BUF *pbuf;

switch(port)

{

caseCOM1:

pbuf = &COM1Buf;

break;

caseCOM2:

pbuf = &COM2Buf;

break;

default:

*err = COM_BAD_CH;

return(0);

}

OS_ENTER_CRITICAL();

if(pbuf->RingBufRxCtr > 0)

{

pbuf->RingBufRxCtr--;

c = *pbuf->RingBufRxOutPtr++;

if(pbuf->RingBufRxOutPtr == &pbuf->RingBufRx[COM_RX_BUF_SIZE])

{

pbuf->RingBufRxOutPtr = &pbuf->RingBufRx[0];

}

OS_EXIT_CRITICAL();

*err = COM_NO_ERR;

return(c);

}else{

OS_EXIT_CRITICAL();

*err = COM_RX_EMPTY;

c = 0;

return(c);

}

}

unsignedcharCOMPutCharB (unsignedcharport, unsignedcharc)

{

// unsigned char cpu_sr;

COM_RING_BUF *pbuf;

switch(port)

{

caseCOM1:

pbuf = &COM1Buf;

break;

caseCOM2:

pbuf = &COM2Buf;

break;

default:

return(COM_BAD_CH);

}

OS_ENTER_CRITICAL();

if(pbuf->RingBufTxCtr < COM_TX_BUF_SIZE) {

pbuf->RingBufTxCtr++;

*pbuf->RingBufTxInPtr++ = c;

if(pbuf->RingBufTxInPtr == &pbuf->RingBufTx[COM_TX_BUF_SIZE]) {

pbuf->RingBufTxInPtr = &pbuf->RingBufTx[0];

}

if(pbuf->RingBufTxCtr == 1) {

COMEnableTxInt(port);

OS_EXIT_CRITICAL();

}else{

OS_EXIT_CRITICAL();

}

return(COM_NO_ERR);

}else{

OS_EXIT_CRITICAL();

return(COM_TX_FULL);

}

}

voidCOMBufferInit (void)

{

COM_RING_BUF *pbuf;

pbuf = &COM1Buf;

pbuf->RingBufRxCtr = 0;

pbuf->RingBufRxInPtr = &pbuf->RingBufRx[0];

pbuf->RingBufRxOutPtr = &pbuf->RingBufRx[0];

pbuf->RingBufTxCtr = 0;

pbuf->RingBufTxInPtr = &pbuf->RingBufTx[0];

pbuf->RingBufTxOutPtr = &pbuf->RingBufTx[0];

pbuf = &COM2Buf;

pbuf->RingBufRxCtr = 0;

pbuf->RingBufRxInPtr = &pbuf->RingBufRx[0];

pbuf->RingBufRxOutPtr = &pbuf->RingBufRx[0];

pbuf->RingBufTxCtr = 0;

pbuf->RingBufTxInPtr = &pbuf->RingBufTx[0];

pbuf->RingBufTxOutPtr = &pbuf->RingBufTx[0];

}

unsignedcharCOMBufferIsEmpty (unsignedcharport)

{

// unsigned char cpu_sr;

unsignedcharempty;

COM_RING_BUF *pbuf;

switch(port)

{

caseCOM1:

pbuf = &COM1Buf;

break;

caseCOM2:

pbuf = &COM2Buf;

break;

default:

return(1);

}

OS_ENTER_CRITICAL();

if(pbuf->RingBufRxCtr > 0)

{

empty = 0;

}

else

{

empty = 1;

}

OS_EXIT_CRITICAL();

return(empty);

}

unsignedcharCOMBufferIsFull (unsignedcharport)

{

// unsigned char cpu_sr;

charfull;

COM_RING_BUF *pbuf;

switch(port)

{

caseCOM1:

pbuf = &COM1Buf;

break;

caseCOM2:

pbuf = &COM2Buf;

break;

default:

return(1);

}

OS_ENTER_CRITICAL();

if(pbuf->RingBufTxCtr < COM_TX_BUF_SIZE) {

full = 0;

}else{

full = 1;

}

OS_EXIT_CRITICAL();

return(full);

}

// This function is called by the Rx ISR to insert a character into the receive ring buffer.

staticvoidCOMPutRxChar (unsignedcharport, unsignedcharc)

{

COM_RING_BUF *pbuf;

switch(port)

{

caseCOM1:

pbuf = &COM1Buf;

break;

caseCOM2:

pbuf = &COM2Buf;

break;

default:

return;

}

if(pbuf->RingBufRxCtr < COM_RX_BUF_SIZE) {

pbuf->RingBufRxCtr++;

*pbuf->RingBufRxInPtr++ = c;

if(pbuf->RingBufRxInPtr == &pbuf->RingBufRx[COM_RX_BUF_SIZE]) {

pbuf->RingBufRxInPtr = &pbuf->RingBufRx[0];

}

}

}

// This function is called by the Tx ISR to extract the next character from the Tx buffer.

// The function returns FALSE if the buffer is empty after the character is extracted from

// the buffer. This is done to signal the Tx ISR to disable interrupts because this is the

// last character to send.

staticunsignedcharCOMGetTxChar (unsignedcharport, unsignedchar*err)

{

unsignedcharc;

COM_RING_BUF *pbuf;

switch(port)

{

caseCOM1:

pbuf = &COM1Buf;

break;

caseCOM2:

pbuf = &COM2Buf;

break;

default:

*err = COM_BAD_CH;

return(0);

}

if(pbuf->RingBufTxCtr > 0) {

pbuf->RingBufTxCtr--;

c = *pbuf->RingBufTxOutPtr++;

if(pbuf->RingBufTxOutPtr == &pbuf->RingBufTx[COM_TX_BUF_SIZE])

{

pbuf->RingBufTxOutPtr = &pbuf->RingBufTx[0];

}

*err = COM_NO_ERR;

return(c);

}else{

*err = COM_TX_EMPTY;

return(0);

}

}

voidUSART1_IRQHandler(void)

{

unsignedintdata;

unsignedcharerr;

if(USART1->SR & 0x0F)

{

// See if we have some kind of error

// Clear interrupt (do nothing about it!)

data = USART1->DR;

}

elseif(USART1->SR & USART_FLAG_RXNE)//Receive Data Reg Full Flag

{

data = USART1->DR;

COMPutRxChar(COM1, data);// Insert received character into buffer

}

elseif(USART1->SR & USART_FLAG_TXE)

{

data = COMGetTxChar(COM1, &err);// Get next character to send.

if(err == COM_TX_EMPTY)

{// Do we have anymore characters to send ?

// No, Disable Tx interrupts

//USART_ITConfig(USART1, USART_IT_TXE| USART_IT_TC, ENABLE);

USART1->CR1 &= ~USART_FLAG_TXE | USART_FLAG_TC;

}

else

{

USART1->DR = data;// Yes, Send character

}

}

}

voidUSART2_IRQHandler(void)

{

unsignedintdata;

unsignedcharerr;

if(USART2->SR & 0x0F)

{

// See if we have some kind of error

// Clear interrupt (do nothing about it!)

data = USART2->DR;

}

elseif(USART2->SR & USART_FLAG_RXNE)//Receive Data Reg Full Flag

{

data = USART2->DR;

COMPutRxChar(COM2, data);// Insert received character into buffer

}

elseif(USART2->SR & USART_FLAG_TXE)

{

data = COMGetTxChar(COM2, &err);// Get next character to send.

if(err == COM_TX_EMPTY)

{// Do we have anymore characters to send ?

// No, Disable Tx interrupts

//USART_ITConfig(USART2, USART_IT_TXE| USART_IT_TC, ENABLE);

USART2->CR1 &= ~USART_FLAG_TXE | USART_FLAG_TC;

}

else

{

USART2->DR = data;// Yes, Send character

}

}

}


下面給個(gè)例子主程序,來演示如何使用上面的串口驅(qū)動(dòng)代碼。


#include "misc.h"

#include "stm32f10x.h"

#include "com_buffered.h"

voidUART_PutStrB (unsignedcharport, uint8_t *str)

{

while(0 != *str)

{

COMPutCharB(port, *str);

str++;

}

}

voidUSART1_Init(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

USART_InitTypeDef USART_InitStructure;

NVIC_InitTypeDef NVIC_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

GP

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

在工業(yè)控制、音頻處理等高性能嵌入式場(chǎng)景中,某電機(jī)驅(qū)動(dòng)項(xiàng)目通過混合使用寄存器操作與CMSIS-DSP庫,將PID控制周期從120μs縮短至38μs,系統(tǒng)響應(yīng)速度提升3倍。本文將揭秘這種"底層+高層"混合編程模式的核心技巧。

關(guān)鍵字: HAL STM32 寄存器

嵌入式系統(tǒng)開發(fā)手勢(shì)識(shí)別作為非接觸式人機(jī)交互的核心技術(shù),正從實(shí)驗(yàn)室走向消費(fèi)級(jí)應(yīng)用。然而,傳感器采集的原始信號(hào)常因電磁干擾、電源噪聲或機(jī)械抖動(dòng)產(chǎn)生失真,導(dǎo)致識(shí)別準(zhǔn)確率下降。本文以STM32微控制器與PAJ7620手勢(shì)識(shí)別傳感...

關(guān)鍵字: STM32 手勢(shì)識(shí)別 噪聲

在物聯(lián)網(wǎng)設(shè)備開發(fā)中,快速實(shí)現(xiàn)穩(wěn)定可靠的網(wǎng)絡(luò)通信是項(xiàng)目成功的關(guān)鍵。W5500作為一款集成硬件TCP/IP協(xié)議棧的以太網(wǎng)控制器,憑借其"開箱即用"的特性,可大幅縮短STM32平臺(tái)的網(wǎng)絡(luò)功能開發(fā)周期。本文通...

關(guān)鍵字: STM32 W5500

工業(yè)物聯(lián)網(wǎng)設(shè)備開發(fā)中,某智能電表項(xiàng)目曾因ADC采樣中斷響應(yīng)延遲導(dǎo)致數(shù)據(jù)丟失率高達(dá)15%。技術(shù)人員通過重構(gòu)DMA驅(qū)動(dòng)架構(gòu),將數(shù)據(jù)搬運(yùn)效率提升12倍,CPU占用率從38%降至3%,成功解決高速采樣場(chǎng)景下的實(shí)時(shí)性難題。這一案例...

關(guān)鍵字: STM32 DMA

工業(yè)機(jī)器人關(guān)節(jié)控制系統(tǒng)中,一個(gè)典型的伺服驅(qū)動(dòng)器需要在100μs周期內(nèi)完成電流采樣、位置反饋、PID計(jì)算和PWM輸出等12項(xiàng)關(guān)鍵任務(wù)。當(dāng)傳統(tǒng)固定優(yōu)先級(jí)調(diào)度導(dǎo)致機(jī)械臂出現(xiàn)0.3°的位置抖動(dòng)時(shí),某運(yùn)動(dòng)控制廠商通過引入混合排序算...

關(guān)鍵字: 電機(jī)控制 STM32

在STM32嵌入式系統(tǒng)開發(fā)中,排序算法的效率直接影響傳感器數(shù)據(jù)處理、通信協(xié)議解析等核心任務(wù)的實(shí)時(shí)性。傳統(tǒng)快速排序在部分有序數(shù)據(jù)場(chǎng)景下易退化為O(n2)時(shí)間復(fù)雜度,而單純依賴三數(shù)取中法優(yōu)化基準(zhǔn)值選擇仍存在小規(guī)模數(shù)據(jù)效率不足...

關(guān)鍵字: STM32 傳感器

在智慧農(nóng)業(yè)的廣闊田野里,部署著數(shù)百個(gè)土壤濕度傳感器節(jié)點(diǎn)。這些節(jié)點(diǎn)通過LoRa模塊將數(shù)據(jù)傳輸至網(wǎng)關(guān),再由網(wǎng)關(guān)上傳至云端進(jìn)行分析。然而,當(dāng)暴雨來臨前,土壤濕度驟增的緊急數(shù)據(jù)若淹沒在常規(guī)監(jiān)測(cè)數(shù)據(jù)的洪流中,可能導(dǎo)致灌溉系統(tǒng)未能及...

關(guān)鍵字: STM32 無線通信 LoRa

在電池管理系統(tǒng)(BMS)中,電壓均衡是保障電池組性能與壽命的核心技術(shù)。由于電池單體存在制造差異,串聯(lián)使用過程中易出現(xiàn)電壓不一致現(xiàn)象,導(dǎo)致部分電池過充/過放,加速老化。傳統(tǒng)被動(dòng)均衡通過能耗電阻消耗高電壓?jiǎn)误w的能量,但存在效...

關(guān)鍵字: BMS系統(tǒng) STM32

在嵌入式系統(tǒng)中,模數(shù)轉(zhuǎn)換器(ADC)是連接物理世界與數(shù)字處理的核心橋梁。STM32系列微控制器內(nèi)置的ADC采用逐次逼近型(SAR)架構(gòu),通過精密的硬件電路實(shí)現(xiàn)模擬信號(hào)到數(shù)字信號(hào)的轉(zhuǎn)換。

關(guān)鍵字: ADC STM32

STM32系列微控制器因其高性能和豐富的外設(shè)接口被廣泛應(yīng)用于各類場(chǎng)景。當(dāng)涉及USB高速(HS)與全速(FS)接口設(shè)計(jì)時(shí),開發(fā)者常因?qū)π盘?hào)完整性、ESD防護(hù)及電源管理的理解不足而陷入調(diào)試?yán)Ь场1疚膶脑沓霭l(fā),結(jié)合實(shí)際案例...

關(guān)鍵字: STM32 USB
關(guān)閉