STM32的串口空閑中斷及接受數據


源程序:

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傳輸完成

}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM