(STM32 A串列埠2)接收(STM32 B資料printf2),同時STM32 A使用串列埠1printf給電腦
阿新 • • 發佈:2019-01-01
一.遇到的問題:
1. 首先是想使用第二個串列埠,查了一下中文手冊,但是好像並沒有關於第二個串列埠配置的,於是就自己寫了一個
2. 在寫串列埠2的時候遇到的問題是如何使用printf()函式,才能不與第一個串列埠向衝突,找了一下百度,通過一個函式就可以搞定了,下文配上
3. 當深入研究串列埠的時候發現很多問題,一個是資料接收儲存問題,雖然是利用串列埠中斷,但是資料在中斷中無法讀取(添加了定時器定時讀取資料,從而使大資料不在堵塞)
4. 就上述三個問題處理,深入處理串列埠問題
二.針對於串列埠2配置問題,手冊使用IO TX->A2 RX->A3
1.在初始化的時候還是老樣子
void usart2_init(u32 bound)
2.串列埠2中斷也是直接改過來的(正點原子例程)
void USART2_IRQHandler(void) //串列埠2中斷服務程式 { u8 Res,t; if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //接收中斷(接收到的資料必須是0x0d 0x0a結尾) { Res =USART_ReceiveData(USART2); //讀取接收到的資料 if((USART2_RX_STA&0x8000)==0)//接收未完成 { if(USART2_RX_STA&0x4000)//接收到了0x0d { if(Res!=0x0a)USART2_RX_STA=0;//接收錯誤,重新開始 else USART2_RX_STA|=0x8000; //接收完成了 } else //還沒收到0X0D { if(Res==0x0d)USART2_RX_STA|=0x4000; else { USART2_RX_BUF[USART2_RX_STA&0X3FFF]=Res ; USART2_RX_STA++; if(USART2_RX_STA>(USART2_REC_LEN-1))USART2_RX_STA=0;//接收資料錯誤,重新開始接收 } } } } }
3.以下為實現printf()函式,想要使用在那個串列埠,直接修改一下USARTX就行了
/串列埠2的printf/
// CMD_BUFFER_LEN長度自己定義吧
void printf2(char *fmt, ...) { char buffer[CMD_BUFFER_LEN+1]; u8 i = 0; va_list arg_ptr; va_start(arg_ptr, fmt); vsnprintf(buffer, CMD_BUFFER_LEN+1, fmt, arg_ptr); while ((i < CMD_BUFFER_LEN) && buffer[i]) { USART_SendData(USART2, (u8) buffer[i++]); while (USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET); } va_end(arg_ptr); }
5. 在上面那個中斷中測試接收到的資料時候出現了些問題,總是卡死或者顯示兩次不完整的資料,於是便自己寫了一個串列埠顯示函式如下
void receive_usart2_handle()
{
if(USART2_RX_STA&0x8000)
{
// len=USART2_RX_STA&0x3fff;//得到此次接收到的資料長度
printf("\r\n您傳送串列埠2的訊息為:\r\n");
printf("%s\r\n",USART2_RX_BUF);
memset(USART2_RX_BUF,0,sizeof(USART2_RX_BUF));//清除buffer
USART2_RX_STA=0;
}
}
6. 下面是定時器2的定時器中斷,因為主函式有延時,不能及時顯示接收資料,從而使定時器不斷掃描,及時傳遞資料,使得資料不再卡頓堵塞
void TIM2_IRQHandler(void) //TIM2中斷
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) //檢查TIM2更新中斷髮生與否
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update ); //清除TIMx更新中斷標誌
receive_usart1_handle();
receive_usart2_handle();
}
}
以下是定時器2的中斷配置
void TIM2_Int_Init(u16 arr,u16 psc) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //時鐘使能 //定時器TIM2初始化 TIM_TimeBaseStructure.TIM_Period = arr; //設定在下一個更新事件裝入活動的自動重灌載暫存器週期的值 TIM_TimeBaseStructure.TIM_Prescaler =psc; //設定用來作為TIMx時鐘頻率除數的預分頻值 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //設定時鐘分割:TDTS = Tck_tim TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上計數模式 TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //根據指定的引數初始化TIMx的時間基數單位 TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE ); //使能指定的TIM2中斷,允許更新中斷 // //中斷優先順序NVIC設定 NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //TIM2中斷 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先佔優先順序0級 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //從優先順序3級 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能 NVIC_Init(&NVIC_InitStructure); //初始化NVIC暫存器 TIM_Cmd(TIM2, ENABLE); //使能TIMx }
8.從而主函式初始化就能夠進行通訊了