usart串口使用

来源:互联网 发布:linux添加永久默认路由 编辑:程序博客网 时间:2024/06/06 12:23


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);  \\接收完数据后失能中断
        }

    }


以上内容为个人使用过程的方法笔记及个人认为的注意点、知识点,内容不全面,如之后使用有所补充随时更新。如您发现有所问题,希望给我意见。


0 0