STM32的串口空閑中斷及接受數據——STM32簡介
STM32系列基于專為要求高性能、低成本、低功耗的嵌入式應用專門設計的ARM Cortex-M3內核
STM32的串口空閑中斷及接受數據——關于什么是空閑中斷:
檢測到接收數據后,在數據總線上的一個字節時間內,沒有接收到數據觸發空閑中斷。RXNE置位一次,空閑總線就檢測一次。
關于STM32串口空閑中斷的問題
1.空閑中斷是接受數據后出現一個byte的高電平(空閑)狀態,就會觸發空閑中斷。并不是空閑就會一直中斷,準確的說應該是上升沿(停止位)后一個byte,如果一直是低電平是不會觸發空閑中斷的(會觸發break中斷)。
2.關于第二點有要鋪墊的三個情況,datasheet中
“當一空閑幀被檢測到時,其處理步驟和接收到普通數據幀一樣,但如果IDLEIE位被設置將產生一個中斷”
“空閑符號被視為完全由‘1’組成的一個完整的數據幀,后面跟著包含了數據的下一幀的開始位‘1’的位數也包括了停止位的位數” 空閑符號的配圖后面跟這一個低電平。
有人理解為只有收到下一個數據的起始位才會觸發中斷,這樣理解是不對的,應該是數據后有空閑了一幀就會觸發。
3.清中斷的方式感覺奇怪,使用函數USART_ClearITPendingBit( USART1, USART_IT_IDLE )清除不了中斷的。我用的是3.5的庫,查看函數說明,里面的@param參數并沒有IDLE,后面的@note中,這樣說:
”PE(Parity error),FE(Framing error),NE(Noise error),ORE(OverRun error) and IDLE(Idle line detected) pending bits are cleared by software sequence: a read operation to USART_SR register (USART_GetITStatus()) followed by a read operation to USART_DR register (USART_ReceiveData())。“
我是通過語句”USART1-》DR;“來清除IDLE中斷的。
關于STM32的串口空閑中斷及接受數據——解析
整體的思路
一開始設置好DMA接收,可以把緩沖區長度設置為幀最大長度,我們可以把RX連接到定時器的管腳輸入端,并且一開始設置輸入并且使能引腳下降沿中斷,當幀的第一個字節發送時,因為起始位為低電平,空閑時UART為高電平,滿足條件,進入中斷,禁止中斷,并且在中斷中開啟定時器,該定時器工作在復位模式,上升沿復位,并且設置好定時器輸出比較值為超時時間,比如20ms,這樣,在傳輸后面字節時,肯定會有高低電平出現,即便是傳輸的是0x00,0xFF,雖然UART數據區不變,但是都為1,或都為0,但是因為起始位為低電平,停止位是高電平,所以肯定會有上升沿,定時器會一直復位,輸出定時器的計數器一直到達不了輸出比較值,當一幀傳輸結束后,定時在最后一個字節復位后,由于沒有數據繼續到達,無法復位,則計數器就能計到輸出比較值,這時發出中斷,在定時器中斷中可以計算出接收數據的長度,并且通知外部數據已經接收完畢。)
另一種USART DMA接收未知數據長度的接收,使用的是USRAT空閑總線中斷接收,這種方法也在網站上比較多見,使用DMA發送USART數據替代了以前的查詢法發送,其速度快了很多,尤其是在大量數據傳輸與發送的時候其優勢更加明顯。
舉個例子:
1、后臺數據-》USART1-》 USART2-》其它設備,其它設備數據-》USART2-》 USART1-》后臺,這兩個數據過程也可能同時進行。
2、由于硬件的限制,USART1和USART2的傳輸波特率不一樣,比如USART1使用GPRS通信,USART2使用短距離無線通信;或者USART1使用以太網通信,USART2使用485總線通信。
現在我把我實現的過程簡單描述一下:
1、 初始化設置:USART1_RX DMA1_ Channel5,USART2_RX DMA1_ Channel6,USART1_TX DMA1_ Channel4,USART2_TX DMA1_ Channel7(具體設置請看程序包)
2、 當數據發送給USART1接收完畢時候會引起USART1的串口總線中斷,計算DMA1_ Channel5內存數組剩余容量,得到接收的字符長度。將接收的字符給DMA1_ Channel4內存數組,啟動DMA1_ Channel4通道傳輸數據,(傳輸完成需要關閉。)下一次數據接收可以在啟動DMA1_ Channel4時候就開始,不需要等待DMA1_ Channel4數據傳輸完成。但是上一次DMA1_ Channel4完成之前,不可以將數據給DMA1_ Channel4內存數組,會沖掉以前數據。
3、 USART2類同USART1。
#e#
源程序:
IO口定義:
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* 第1步:打開GPIO和USART部件的時鐘 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
/* 第2步:將USART Tx的GPIO配置為推挽復用模式 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* 第3步:將USART Rx的GPIO配置為浮空輸入模式
由于CPU復位后,GPIO缺省都是浮空輸入模式,因此下面這個步驟不是必須的
但是,我還是建議加上便于閱讀,并且防止其它地方修改了這個口線的設置參數
*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* 第1步:打開GPIO和USART2部件的時鐘 */
//RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
/* 第2步:將USART2 Tx的GPIO配置為推挽復用模式 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* 第3步:將USART2 Rx的GPIO配置為浮空輸入模式
由于CPU復位后,GPIO缺省都是浮空輸入模式,因此下面這個步驟不是必須的
但是,我還是建議加上便于閱讀,并且防止其它地方修改了這個口線的設置參數
*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* 第3步已經做了,因此這步可以不做
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
*/
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
串口初始化:
void USART_Configuration(void)
{
USART_InitTypeDef USART_InitStructure;
/* 第4步:配置USART參數
- BaudRate = 115200 baud
- Word Length = 8 Bits
- One Stop Bit
- No parity
- Hardware flow control disabled (RTS and CTS signals)
- Receive and transmit enabled
*/
USART_InitStructure.USART_BaudRate = 19200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
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);
//配置USART1空閑中斷
USART_ITConfig(USART1, USART_IT_IDLE , ENABLE);
/* 第5步:使能 USART, 配置完畢 */
USART_Cmd(USART1, ENABLE);
/* CPU的小缺陷:串口配置好,如果直接Send,則第1個字節發送不出去
如下語句解決第1個字節無法正確發送出去的問題 */
USART_ClearFlag(USART1, USART_FLAG_TC); /* 清發送完成標志,Transmission Complete flag */
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
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(USART2, &USART_InitStructure);
//配置USART2空閑中斷
USART_ITConfig(USART2, USART_IT_IDLE , ENABLE);
USART_Cmd(USART2, ENABLE);
/* CPU的小缺陷:串口配置好,如果直接Send,則第1個字節發送不出去
如下語句解決第1個字節無法正確發送出去的問題 */
USART_ClearFlag(USART2, USART_FLAG_TC); /* 清發送外城標志,Transmission Complete flag */
}
DMA配置:
void DMA_Configuration(void)
{
DMA_InitTypeDef DMA_InitStructure;
/* DMA clock enable */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //開啟DMA1外設時鐘
/* DMA1 Channel4 (triggered by USART1 Tx event) Config */
DMA_DeInit(DMA1_Channel4);
DMA_InitStructure.DMA_PeripheralBaseAddr = 0x40013804;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)USART1_SEND_DATA;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = 512;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //循環模式
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel4, &DMA_InitStructure);
DMA_ITConfig(DMA1_Channel4, DMA_IT_TC, ENABLE);
DMA_ITConfig(DMA1_Channel4, DMA_IT_TE, ENABLE);
/* Enable USART1 DMA TX request */
USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
DMA_Cmd(DMA1_Channel4, DISABLE);
/* DMA1 Channel5 (triggered by USART2 Tx event) Config */
DMA_DeInit(DMA1_Channel7);
DMA_InitStructure.DMA_PeripheralBaseAddr = 0x40004404;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)USART2_SEND_DATA;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = 512;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel7, &DMA_InitStructure);
DMA_ITConfig(DMA1_Channel7, DMA_IT_TC, ENABLE);
DMA_ITConfig(DMA1_Channel7, DMA_IT_TE, ENABLE);
/* Enable USART1 DMA TX request */
USART_DMACmd(USART2, USART_DMAReq_Tx, ENABLE);
DMA_Cmd(DMA1_Channel7, DISABLE);
/* DMA1 Channel5 (triggered by USART1 Rx event) Config */
DMA_DeInit(DMA1_Channel5);
DMA_InitStructure.DMA_PeripheralBaseAddr = 0x40013804;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)USART1_RECEIVE_DATA;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = 512;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel5, &DMA_InitStructure);
DMA_ITConfig(DMA1_Channel5, DMA_IT_TC, ENABLE);
DMA_ITConfig(DMA1_Channel5, DMA_IT_TE, ENABLE);
/* Enable USART1 DMA RX request */
USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);
DMA_Cmd(DMA1_Channel5, ENABLE);
/* DMA1 Channel6 (triggered by USART1 Rx event) Config */
DMA_DeInit(DMA1_Channel6);
DMA_InitStructure.DMA_PeripheralBaseAddr = 0x40004404;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)USART2_RECEIVE_DATA;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = 512;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel6, &DMA_InitStructure);
DMA_ITConfig(DMA1_Channel6, DMA_IT_TC, ENABLE);
DMA_ITConfig(DMA1_Channel6, DMA_IT_TE, ENABLE);
/* Enable USART2 DMA RX request */
USART_DMACmd(USART2, USART_DMAReq_Rx, ENABLE);
DMA_Cmd(DMA1_Channel6, ENABLE);
}
中斷優先級配置:
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Configure one bit for preemption priority */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/* Enable the USART1 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* Enable the USART2 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
//Enable DMA Channel4 Interrupt
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
//Enable DMA Channel7 Interrupt
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel7_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/*Enable DMA Channel5 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/*Enable DMA Channel6 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel6_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
數組定義,含義如題名:
u8 USART1_SEND_DATA[512];
u8 USART2_SEND_DATA[512];
u8 USART1_RECEIVE_DATA[512];
u8 USART2_RECEIVE_DATA[512];
u8 USART1_TX_Finish=1; // USART1發送完成標志量
u8 USART2_TX_Finish=1; // USART2發送完成標志量
USART1中斷服務函數
void USART1_IRQHandler(void)
{
u16 DATA_LEN;
u16 i;
if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET) //如果為空閑總線中斷
{
DMA_Cmd(DMA1_Channel5, DISABLE); //關閉DMA,防止處理其間有數據
//USART_RX_STA = USART1-》SR; //先讀SR,然后讀DR才能清除
//USART_RX_STA = USART1-》DR;
DATA_LEN=512-DMA_GetCurrDataCounter(DMA1_Channel5);
if(DATA_LEN 》 0)
{
while(USART1_TX_Finish==0) //等待數據傳輸完成才下一次
{
;
}
//將數據送DMA存儲地址
for(i=0;iTA_LEN;i )
{
USART1_SEND_DATA=USART1_RECEIVE_DATA;
}
//USART用DMA傳輸替代查詢方式發送,克服被高優先級中斷而產生丟幀現象。
DMA_Cmd(DMA1_Channel4, DISABLE); //改變datasize前先要禁止通道工作
DMA1_Channel4-》CNDTR=DATA_LEN; //DMA1,傳輸數據量
USART1_TX_Finish=0; //DMA傳輸開始標志量
DMA_Cmd(DMA1_Channel4, ENABLE);
}
//DMA_Cmd(DMA1_Channel5, DISABLE); //關閉DMA,防止處理其間有數據
DMA_ClearFlag(DMA1_FLAG_GL5 | DMA1_FLAG_TC5 | DMA1_FLAG_TE5 | DMA1_FLAG_HT5);//清標志
DMA1_Channel5-》CNDTR = 512; //重裝填
DMA_Cmd(DMA1_Channel5, ENABLE); //處理完,重開DMA
//讀SR后讀DR清除Idle
i = USART1-》SR;
i = USART1-》DR;
}
if(USART_GetITStatus(USART1, USART_IT_PE | USART_IT_FE | USART_IT_NE) != RESET) //出錯
{
USART_ClearITPendingBit(USART1, USART_IT_PE | USART_IT_FE | USART_IT_NE);
}
USART_ClearITPendingBit(USART1, USART_IT_TC);
USART_ClearITPendingBit(USART1, USART_IT_IDLE);
}
USART2中斷服務函數
void USART2_IRQHandler(void)
{
u16 DATA_LEN;
u16 i;
if(USART_GetITStatus(USART2, USART_IT_IDLE) != RESET) //如果為空閑總線中斷
{
DMA_Cmd(DMA1_Channel6, DISABLE); //關閉DMA,防止處理其間有數據
//USART_RX_STA = USART1-》SR; //先讀SR,然后讀DR才能清除
//USART_RX_STA = USART1-》DR;
DATA_LEN=512-DMA_GetCurrDataCounter(DMA1_Channel6);
if(DATA_LEN 》 0)
{
while(USART2_TX_Finish==0) //等待數據完成才下一次
{
;
}
//將數據送DMA存儲地址
for(i=0;iTA_LEN;i )
{
USART2_SEND_DATA=USART2_RECEIVE_DATA;
}
//USART用DMA傳輸替代查詢方式發送,克服被高優先級中斷而產生丟幀現象。
DMA_Cmd(DMA1_Channel7, DISABLE); //改變datasize前先要禁止通道工作
DMA1_Channel7-》CNDTR=DATA_LEN; //DMA1,傳輸數據量
USART2_TX_Finish=0; //DMA傳輸開始標志量
DMA_Cmd(DMA1_Channel7, ENABLE);
}
//DMA_Cmd(DMA1_Channel5, DISABLE); //關閉DMA,防止處理其間有數據
DMA_ClearFlag(DMA1_FLAG_GL6 | DMA1_FLAG_TC6 | DMA1_FLAG_TE6 | DMA1_FLAG_HT6);//清標志
DMA1_Channel6-》CNDTR = 512; //重裝填
DMA_Cmd(DMA1_Channel6, ENABLE); //處理完,重開DMA
//讀SR后讀DR清除Idle
i = USART2-》SR;
i = USART2-》DR;
}
if(USART_GetITStatus(USART2, USART_IT_PE | USART_IT_FE | USART_IT_NE) != RESET) //出錯
{
USART_ClearITPendingBit(USART2, USART_IT_PE | USART_IT_FE | USART_IT_NE);
}
USART_ClearITPendingBit(USART2, USART_IT_TC);
USART_ClearITPendingBit(USART2, USART_IT_IDLE);
}
DMA1_Channel5中斷服務函數
void DMA1_Channel5_IRQHandler(void)
{
DMA_ClearITPendingBit(DMA1_IT_TC5);
DMA_ClearITPendingBit(DMA1_IT_TE5);
DMA_Cmd(DMA1_Channel5, DISABLE); //關閉DMA,防止處理其間有數據
DMA1_Channel5-》CNDTR = 580; //重裝填
DMA_Cmd(DMA1_Channel5, ENABLE); //處理完,重開DMA
}
DMA1_Channel6中斷服務函數
void DMA1_Channel6_IRQHandler(void)
{
DMA_ClearITPendingBit(DMA1_IT_TC6);
DMA_ClearITPendingBit(DMA1_IT_TE6);
DMA_Cmd(DMA1_Channel6, DISABLE); //關閉DMA,防止處理其間有數據
DMA1_Channel6-》CNDTR = 580; //重裝填
DMA_Cmd(DMA1_Channel6, ENABLE); //處理完,重開DMA
}
DMA1_Channel4中斷服務函數
//USART1使用DMA發數據中斷服務程序
void DMA1_Channel4_IRQHandler(void)
{
DMA_ClearITPendingBit(DMA1_IT_TC4);
DMA_ClearITPendingBit(DMA1_IT_TE4);
DMA_Cmd(DMA1_Channel4, DISABLE); //關閉DMA
USART1_TX_Finish=1; //置DMA傳輸完成
}
DMA1_Channel7中斷服務函數
//USART2使用DMA發數據中斷服務程序
void DMA1_Channel7_IRQHandler(void)
{
DMA_ClearITPendingBit(DMA1_IT_TC7);
DMA_ClearITPendingBit(DMA1_IT_TE7);
DMA_Cmd(DMA1_Channel7, DISABLE);//關閉DMA
USART2_TX_Finish=1;//置DMA傳輸完成
}
評論
查看更多