STM32
直播中

石正厚

7年用户 1106经验值
私信 关注
[问答]

如何去实现基于STM32F103C6的串口USART1功能呢

如何去实现基于STM32F103C6的串口USART1功能呢?串口USART1有何功能呢?



回帖(1)

陈桂平

2021-12-13 14:49:19
基于STM32F103C6工程实现串口USART1功能,USART1串口TX为PA9,RX为PA10,配置一个USART1串口分为以下几步:



  • 初时化IO配置
  • 初时化USART NVIC配置
  • 初时化USART参数
  • 实现中断函数USART1_IRQHandler
  • 实现串口发送函数USART1_Send_Data
  • 主函数调用相关配置函数

Step 1: 初时化IO配置,初时化USART NVIC配置,初时化USART参数封装成一个函数

#include "stm32f10x_usart.h"
#include "stm32f10x.h"
#include

uint8_t rxBuf[40];
uint8_t rxLen;

/**
  * @brief  USART1串口初时化
  *        
  *         
  * @param  uint32_t baudrate[in]:设置波特率
  * @retval None
  */
void Usart1_Init(uint32_t baudrate)
{
        GPIO_InitTypeDef GPIO_InitStructure;
        USART_InitTypeDef USART_InitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;
       
        /* 初时化串口前,先将相应的时钟打开 */
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA,ENABLE);
       
        /* 初时化USART1 TX PA9引脚设为复用推挽输出 */
        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);
       
        /* 初时化USART1 RX PA10引脚为浮空输入 */
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_Init(GPIOA,&GPIO_InitStructure);
       
       
        /* USART1 NVIC初时化 */
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); /*!< 设置NVIC中断分组2:2位抢占优先级,2位响应优先级   0-3; */
        NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; /*!< USART1中断通道USART1_IRQn  */
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; /*!< 抢占优先级3 */
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;    /*!< 子优先级3 */
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  /*!<  IRQ使能通道 */
        NVIC_Init(&NVIC_InitStructure);   /*!< 初时化NVIC寄存器  */
       
        /* USART初时化设置 */
        USART_InitStructure.USART_BaudRate = baudrate;   /*!<  设置波特率 */
        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
        USART_InitStructure.USART_WordLength = USART_WordLength_8b; /*!< 8位数据*/
        USART_InitStructure.USART_StopBits = USART_StopBits_1;   /*!< 1位停止位 */
        USART_InitStructure.USART_Parity = USART_Parity_No;   /*!< 无校验位 */
        USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;  /*!< 收发模式*/
        USART_Init(USART1,&USART_InitStructure);  /*!< 初时化串口1 */
       
        /* 开启串口1接收中断 */
        USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
        /* 使能串口1 */
        USART_Cmd(USART1,ENABLE);

}
Step 2: 实现中断函数USART1_IRQHandler


/**
  * @brief  USART1串口中断函数
  *        
  *         
  * @param  None
  * @retval None
  */
void USART1_IRQHandler(void)
{
        /* 暂存接收结果 */
        uint8_t result;
  /* @note
  *   - PE (Parity error), FE (Framing error), NE (Noise error), ORE (OverRun
  *     error) and IDLE (Idle line detected) pending bits are cleared by
  *     software sequence: a read operation to USART_SR register
  *     (USART_GetITStatus()) followed by a read operation to USART_DR register
  *     (USART_ReceiveData()).
  *   - RXNE pending bit can be also cleared by a read to the USART_DR register
  *     (USART_ReceiveData()).
  */
        /* 检查是否为USART1接收中断 */
        if(USART_GetITStatus(USART1,USART_IT_RXNE) != RESET)
        {
                 result = USART_ReceiveData(USART1);   
                 if(rxLen < 20)
                 {
                         rxBuf[rxLen] = result;
                         rxLen++;
                 }                         
        }
        /* 溢出发生时,先读SR,再读DR,解决中断不进入问题*/
        else if(USART_GetFlagStatus(USART1,USART_IT_ORE) == SET)
        {
                 USART_ClearFlag(USART1,USART_IT_ORE);
                 USART_ReceiveData(USART1);
        }
       
       
       
       

}
Step 3:实现串口发送函数USART1_Send_Data



/**
* @brief  USART1串口发送函数
  *        
  *         
        * @param   uint8_t *buf[in]:待发送的数据buffer
* @param   uint16_t len:发送的数据长度
  * @retval None
  */
void USART1_Send_Data(uint8_t *buf,uint16_t len)
{
        for(uint16_t i = 0; i         {
  /*- TC pending bit can be also cleared by software sequence: a read
  *     operation to USART_SR register (USART_GetITStatus()) followed by a write
  *     operation to USART_DR register (USART_SendData()).
  *   - TXE pending bit is cleared only by a write to the USART_DR register
  *     (USART_SendData()).
  */
                while(USART_GetFlagStatus(USART1,USART_FLAG_TC)); /*!<发送是否完成*/
                USART_SendData(USART1,buf);
        }       
}
Step 4:主函数调用相关配置函数



/**
  * @brief  主函数,程序的入口
  *        
  *         
  * @param  None
  * @retval int:不用理会,对于嵌入式系统,永远都不会返回
  */
int main(void)
{
        Usart1_Init(9600);
        for(;;)
        {
                if(rxLen >= 20)
                {
                        USART1_Send_Data(rxBuf,20);
                        rxLen = 0;
                }
               
        }
}
串口功能完成,那么如何实现printf函数功能呢,重定义fputc函数

//重定义fputc函数
int fputc(int ch, FILE *f)
{      
        while((USART1->SR&0X40)==0);
        USART1->DR = (u8) ch;      
               
        return ch;
}


此时还需要勾选Use MicroLib选项






另一种方法不需要勾选Use MicroLib选项,如下:


/* 加入以下代码,支持printf函数,而不需要选择use MicroLIB */
#ifdef DEBUG
#pragma import(__use_no_semihosting)            
//标准库需要的支持函数                 
struct __FILE
{
        int handle;

};

FILE __stdout;      
//定义_sys_exit()以避免使用半主机模式   
void _sys_exit(int x)
{
        x = x;
}  
//重定义fputc函数
int fputc(int ch, FILE *f)
{      
        while((USART1->SR&0X40)==0);
        USART1->DR = (u8) ch;      
               
        return ch;
}
#endif


断言功能实现,首先得定义宏USE_FULL_ASSERT打开断言功能,然后实现函

数assert_failed

#if USE_FULL_ASSERT
void assert_failed(uint8_t* file, uint32_t line)
{
        printf("rnfile path is %s,error line is %drn",file,line);
        while(1);
}
#endif
举报

更多回帖

×
20
完善资料,
赚取积分