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

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

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

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

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


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ā)送中斷有兩個,分別是:

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

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

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

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


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;

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

}

elseif(USART1->SR & USART_FLAG_TXE)

{

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

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

}

}

}


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


#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

}

}

}


下面給個例子主程序,來演示如何使用上面的串口驅動代碼。


#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

本站聲明: 本文章由作者或相關機構授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內容真實性等。需要轉載請聯(lián)系該專欄作者,如若文章內容侵犯您的權益,請及時聯(lián)系本站刪除( 郵箱:macysun@21ic.com )。
換一批
延伸閱讀
關閉