1. 程式人生 > >(STM32 A串列埠2)接收(STM32 B資料printf2),同時STM32 A使用串列埠1printf給電腦

(STM32 A串列埠2)接收(STM32 B資料printf2),同時STM32 A使用串列埠1printf給電腦

一.遇到的問題:
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();
        }
}
  1. 以下是定時器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.從而主函式初始化就能夠進行通訊了