usart串口使用



stm32串口使用:

1、printf函數調用

        IAR的option設置中將printf庫打開再編寫printf重定向到usartn的函數

        int fputc(int ch, FILE *f)

        {
            /* Place your implementation of fputc here */

            /* e.g. write a character to the USART */

            USART_SendData(USART1, (uint8_t) ch);

            /* Loop until transmit data register is empty */

            while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)
            {
            }
            return ch;
        }

        使用usb轉TTL直接連接MCU與計算機即可。

        除TTL外,rs232與rs485都可作爲串口線使用。

        使用區別在於232餘485電平不同

        接線不同rs232三線制 TX、RX、GND 全雙工通信,rs485兩線制 ,485+、485- 半雙工通信(接法不同也可全雙工通信,資料所說,沒調試過)

        通信協議,rs232點對點通信,rs485總線形式通信。 

        傳輸距離不同,rs485可傳輸幾十米到上千米rs232有效傳輸距離爲15米。

        使用接線與芯片不同,mcu使用232芯片,即使用232串口線,使用485芯片即使用485串口線。

2、串口收發

       串口接收:

       關鍵點:初始化中的1、波特率 2、使能接收中斷    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);  其餘初始化按部就班

static void Bsp_UsartInit(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
    GPIO_InitTypeDef  GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef  NVIC_InitStructure;
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1); 
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);    
    /* Configure pins as AF pushpull */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);  
    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( USART1,&USART_InitStructure);  
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); 
    USART_Cmd(USART1,ENABLE);
    /* USART1 IRQ Channel configuration */
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPriority = 0x01;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

串口讀取函數,該函數兼容一個MCU多個串口根據定義的串口號來調用同個函數,使用讀寫wp rp 位置指針存取讀取數據

uint8 Sys_ComReadByte(uint8 ComNum, uint8 *pData,uint8 len)
{
    if(ComNum >= SYS_COM_NUM)   //多個串口使用 
    {
        return FALSE;
    }
    if(g_Data.ComInfo.DevToApp[ComNum].rp == g_Data.ComInfo.DevToApp[ComNum].wp)
    {
        return FALSE;
    }
    for(int i=0;i<len;i++)
    {
        *pData++ = g_Data.ComInfo.DevToApp[ComNum].Data[g_Data.ComInfo.DevToApp[ComNum].rp];
        g_Data.ComInfo.DevToApp[ComNum].rp = (g_Data.ComInfo.DevToApp[ComNum].rp+1)%SYS_COM_BUF_SIZE;
    }
    return TRUE;
}

中斷函數中接收數據

    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
    {
        /* Read one byte from the receive data register */
        g_Data.ComInfo.DevToApp[BSP_485_COM].Data[g_Data.ComInfo.DevToApp[BSP_485_COM].wp] = (USART_ReceiveData(USART1) & 0x7F);
        g_Data.ComInfo.DevToApp[BSP_485_COM].wp = (g_Data.ComInfo.DevToApp[BSP_485_COM].wp+1)%SYS_COM_BUF_SIZE;
    }  

    串口發送:

      使用串口發送中斷,中斷分爲兩種一種爲USART_IT_TC第二種爲USART_IT_TXE

     使用過程中碰到一個問題是,當串口初始化完之後,使能了USART_IT_TC中斷,並且打開了總中斷後程序一直進入中斷,跳不出來。

     後查詢原因解釋說,TC中斷全稱爲transmission complete,發送完中斷,在初始化使能中斷後會自動發送一個空閒幀。我試過在使能中斷之前或者之後或者在中斷函數裏都       單獨進行清TC標誌位,但退不出中斷。後改使用TXE中斷

   TXE中斷即爲TX DR EMPTY 發送寄存器爲空就產生中斷,所以使用過程中的順序爲,初始化時不使能中斷,在調用發送函數後,或使用寄存器操作時當該寄存器不爲空時使能    該中斷USART_IT_TXE,然後在串口中斷裏當接收完所有數據後失能該中斷,以保證不會重複進入中斷

串口寫入數據函數:該函數兼容一個MCU多個串口使用,使用定義串口號來使用,並使用讀寫rp與wp位置指針 

uint16 Sys_ComWrite(uint8 ComNum, uint8 *pData, uint16 SLen)
{
    if(ComNum >= SYS_COM_NUM)
    {
        return FALSE;
    }
    if(SLen==0)
    {
        return FALSE;
    }
    Bsp_SetDealyMs(SYS_COM_SEND_DELAY_TIME);
    while(1)/* 等待緩衝區的數據全部發送完成 */
    {
        if((g_Data.ComInfo.AppToDev[ComNum].rp==0)
         &&(g_Data.ComInfo.AppToDev[ComNum].wp==0))
        {
            break;
        }
        if(!Bsp_GetDealyMs())
        {
            break;
        }
    }
    memcpy(g_Data.ComInfo.AppToDev[ComNum].Data, pData, SLen);
    g_Data.ComInfo.AppToDev[ComNum].rp = 1;
    g_Data.ComInfo.AppToDev[ComNum].wp = SLen;
    switch(ComNum)
    {
        case 0:
                break;
        case 1:
                USART_SendData(USART1, g_Data.ComInfo.AppToDev[ComNum].Data[0]); 
                USART_ITConfig(USART1, USART_IT_TXE, ENABLE); // 發送寄存器爲空產生中斷,固要在發送函數後打開中斷使能,中斷接收完數據後失能
                break;
        case 2:
                break;
        default:
                break;
    }
    Bsp_SetDealyMs(0);    
    return SLen;
}

接收中斷內容

 if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)
    {    
        
        /* Write one byte to the transmit data register */
        if(g_Data.ComInfo.AppToDev[BSP_485_COM].wp > g_Data.ComInfo.AppToDev[BSP_485_COM].rp)
        {
           
            USART_SendData(USART1, g_Data.ComInfo.AppToDev[BSP_485_COM].Data[g_Data.ComInfo.AppToDev[BSP_485_COM].rp]);
            g_Data.ComInfo.AppToDev[BSP_485_COM].rp = (g_Data.ComInfo.AppToDev[BSP_485_COM].rp+1)%SYS_COM_BUF_SIZE;
        }
        else
        {
             g_Data.ComInfo.AppToDev[BSP_485_COM].wp = 0;
             g_Data.ComInfo.AppToDev[BSP_485_COM].rp = 0;  
             USART_ITConfig(USART1, USART_IT_TXE, DISABLE);  \\接收完數據後失能中斷
        }

    }


以上內容爲個人使用過程的方法筆記及個人認爲的注意點、知識點,內容不全面,如之後使用有所補充隨時更新。如您發現有所問題,希望給我意見。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章