zoukankan      html  css  js  c++  java
  • STM32调试大法 之 串口通讯

    开发过程经常需要查看某些特定参数。通常的方法可以使用paintf进行打印输出,观察具体的变量值。STM32内部集成有USART的串口功能,可以通过串口直接输出到电脑(上位机)。使用非常方便,基本不需要不需要写代码,只要配置一下就可以使用。

    简单设置就可以看到上面的效果

    配置方法:

      1、重定向printf的输出函数 int fputc(int ch, FILE *f)

      2、配置STM32F10x的USART串口

    重定向方法 stdio.h 的输出内容

    int fputc(int ch, FILE *f)
    {
      // 等待USART1 数据发送完成(发送区域空)
      while (!(USART1->SR & USART_SR_TXE));
      // 填充发送寄存器,数据 + 校验位 最多9位
      USART1->DR = (ch & 0x1FF);
      
      return (ch);
    }

    启动STM32的 USART1 串口

        1、使能 复用功能

        2、使能 A引脚(USART1 在 PA9,PA10)

        3、使能 USART1

        4、设置 PA9(TX)复用推挽输出

        5、设置 PA10(RX)输入浮空

        6、 设置串口参数:波特率、数据位、校验、停止位、流控制

        7、使能串口、使能输入、使能输出

        OK

    void serial_init(void)
    {
      //
      //  设置串口调试
      //   
      //     输  出: USART1
      //     引  脚: PA9(TX), PA10(RX)
      //     波特率: 9600
      //     数据位: 8 bit (default)  (CR1)
      //     校  验: none  (default)  (CR1)
      //     停止位: 1 bit (default)  (CR2)
      //     流控制: none  (default)  (CR3)
      //
      // 清除设置后上面配置为系统默认状态
      
      int i;
      /// 使能复用功能,使能GPIOA,使能USART1
      RCC->APB2ENR |= RCC_APB2ENR_AFIOEN | RCC_APB2ENR_IOPAEN | RCC_APB2ENR_USART1EN;
      // 关闭映射,确保USART使用 PA9,PA10
      AFIO->MAPR &= ~AFIO_MAPR_USART1_REMAP;
      
      // 清除PA9,PA10状态
      GPIOA->CRH &= ~( GPIO_CRH_CNF9 | GPIO_CRH_MODE9 | 
                       GPIO_CRH_CNF10 | GPIO_CRH_MODE10 );
      // 设置PA9 发送 为复用推挽输出 2MHz
      GPIOA->CRH |= GPIO_CR_AFOUT_PP2MHz & ( GPIO_CRH_CNF9 | GPIO_CRH_MODE9 );
      // 设置PA10接收 为复用上拉下拉模式
      GPIOA->CRH |= GPIO_CR_AFIN_PULLDOWN & ( GPIO_CRH_CNF10 | GPIO_CRH_MODE10 );
      
    
      // 设置波特率为 9600
      // 计算方法
      //          系统时钟 / (16分频 * 波特率)
      //   Baud = 72,000,000 / (16 * 9600) = 468.75
      //   整数部分 << 4 + 取整(小数部分 * 16)
      //   468 << 4 + 0.75 * 16
      USART1->BRR = __USART_BRR(SystemCoreClock, 9600);
      
      // 清除寄存器状态
      USART1->CR1 = USART_CR1_REST;
      USART1->CR2 = USART_CR2_REST;           // 停止位 1
      USART1->CR3 = USART_CR3_REST;           // 没用控制流
      
      // 防止产生不必要的信息
      for (i = 0; i < 0x1000; i++) __NOP();
      
      // USART1 使能, 使能输出,使能输入
      USART1->CR1 =  USART_CR1_UE | USART_CR1_TE | USART_CR1_RE;
      
    }

    整个过程中关键的输出定向主要用到了2个寄存器:

       一个状态寄存器,检查发送是否为空(USART_ST_TXE)

      一个数据寄存器,用于发送数据

    int main(void)
    {
      uint8_t ud = 'a';
      Delay_init();
      // 初始化串口调试
      serial_init();
      
      // 使用寄存器直接 输出 a~z
      while (ud <= 'z') {
        while (!(USART1->SR & USART_SR_TXE));
        USART1->DR = ud;
        ud++;
      }
        
      // 使用打印重定向输出字符串
      printf("
    test!
    ");
      printf("USART1 使能, 使能输出,使能输入
    ");
      
      ud = 'a';
      while (1) {  
        Delay(20); // 太快降低速度方便看结果(200ms延迟)
        // 使用寄存器直接输出
        while (!(USART1->SR & USART_SR_TXE));
        USART1->DR = ud;
        ud++;    
        
        // 使用打印输出换行
        if (ud > 'z') {
          ud = 'a';
          printf("
    ");  
        }
      };       
      
    }

    具体的配置寄存器可以查看《参考手册》

    完整代码

    #define GPIO_CR_RESET                 (uint32_t)0x44444444 
    #define GPIO_CR_MODE_INPUT            (uint32_t)0x00000000
    #define GPIO_CR_MODE_2MHz             (uint32_t)0x22222222
    #define GPIO_CR_MODE_10MHz            (uint32_t)0x11111111
    #define GPIO_CR_MODE_50MHz            (uint32_t)0x33333333
    
    #define GPIO_CR_GP_PUSHPULL           (uint32_t)0x00000000
    #define GPIO_CR_GP_OPENDRAIN          (uint32_t)0x44444444 
    #define GPIO_CR_OUT_PP2MHz            (GPIO_CR_MODE_2MHz | GPIO_CR_GP_PUSHPULL)
    #define GPIO_CR_OUT_PP50MHz           (GPIO_CR_MODE_50MHz | GPIO_CR_GP_PUSHPULL)
    
       
    #define GPIO_CR_AFO_PUSHPULL           (uint32_t)0x88888888
    #define GPIO_CR_AFO_OPENDRAIN          (uint32_t)0xcccccccc 
    
    #define GPIO_CR_AFOUT_PP2MHz          (GPIO_CR_MODE_2MHz | GPIO_CR_AFO_PUSHPULL)  // 复用推挽输出,2MHz
    #define GPIO_CR_AFIN_FLOAT            (uint32_t)0x44444444  // 复用开漏输入
    #define GPIO_CR_AFIN_PULLDOWN         (uint32_t)0x88888888  // 复用上拉下拉输入
    
    
    #define USART_CR1_REST                (uint32_t)0x00000000
    #define USART_CR2_REST                (uint32_t)0x00000000
    #define USART_CR3_REST                (uint32_t)0x00000000
    常量定义
    /**
      ********************************************************************
      *
      * @file     serial.c
      * @author   fpack
      * @version  v1.0
      * @date     2014-9-1
      * @brief    小穆妹纸串口调试
      *
      ********************************************************************
      **/
    
    #include <stdio.h>
    #include "armsis.h"
    
    /*----------------------------------------------------------------------------
     Define  Baudrate setting (BRR) for USART
     *----------------------------------------------------------------------------*/
    #define __DIV(__PCLK, __BAUD)       ((__PCLK*25)/(4*__BAUD))
    #define __DIVMANT(__PCLK, __BAUD)   (__DIV(__PCLK, __BAUD)/100)
    #define __DIVFRAQ(__PCLK, __BAUD)   (((__DIV(__PCLK, __BAUD) - (__DIVMANT(__PCLK, __BAUD) * 100)) * 16 + 50) / 100)
    #define __USART_BRR(__PCLK, __BAUD) ((__DIVMANT(__PCLK, __BAUD) << 4)|(__DIVFRAQ(__PCLK, __BAUD) & 0x0F))
    
    
    //struct __FILE { int handle; /* Add whatever you need here */ };
    //FILE __stdout;
    //FILE __stdin;
    
    int fputc(int ch, FILE *f)
    {
      // 等待USART1 数据发送完成(发送区域空)
      while (!(USART1->SR & USART_SR_TXE));
      USART1->DR = (ch & 0x1FF);
      
      return (ch);
    }
    
    
    void serial_init(void)
    {
      //
      //  设置串口调试
      //   
      //     输  出: USART1
      //     引  脚: PA9(TX), PA10(RX)
      //     波特率: 9600
      //     数据位: 8 bit (default)  (CR1)
      //     校  验: none  (default)  (CR1)
      //     停止位: 1 bit (default)  (CR2)
      //     流控制: none  (default)  (CR3)
      //
      // 清除设置后上面配置为系统默认状态
      
      int i;
      /// 使能复用功能,使能GPIOA,使能USART1
      RCC->APB2ENR |= RCC_APB2ENR_AFIOEN | RCC_APB2ENR_IOPAEN | RCC_APB2ENR_USART1EN;
      // 关闭映射,确保USART使用 PA9,PA10
      AFIO->MAPR &= ~AFIO_MAPR_USART1_REMAP;
      
      // 清除PA9,PA10状态
      GPIOA->CRH &= ~( GPIO_CRH_CNF9 | GPIO_CRH_MODE9 | 
                       GPIO_CRH_CNF10 | GPIO_CRH_MODE10 );
      // 设置PA9 发送 为复用推挽输出 2MHz
      GPIOA->CRH |= GPIO_CR_AFOUT_PP2MHz & ( GPIO_CRH_CNF9 | GPIO_CRH_MODE9 );
      // 设置PA10接收 为复用上拉下拉模式
      GPIOA->CRH |= GPIO_CR_AFIN_PULLDOWN & ( GPIO_CRH_CNF10 | GPIO_CRH_MODE10 );
      
    
      // 设置波特率为 9600
      // 计算方法
      //          系统时钟 / (16分频 * 波特率)
      //   Baud = 72,000,000 / (16 * 9600) = 468.75
      //   整数部分 << 4 + 取整(小数部分 * 16)
      //   468 << 4 + 0.75 * 16
      USART1->BRR = __USART_BRR(SystemCoreClock, 9600);
      
      // 清除寄存器状态
      USART1->CR1 = USART_CR1_REST;
      USART1->CR2 = USART_CR2_REST;           // 停止位 1
      USART1->CR3 = USART_CR3_REST;           // 没用控制流
      
      // 防止产生不必要的信息
      for (i = 0; i < 0x1000; i++) __NOP();
      
      // USART1 使能, 使能输出,使能输入
      USART1->CR1 =  USART_CR1_UE | USART_CR1_TE | USART_CR1_RE;
      
    }
    整理后的串口配置代码 Serial.c
    /**
      ********************************************************************
      *
      * @file     serial.h
      * @author   fpack
      * @version  v1.0
      * @date     2014-9-1
      * @brief    小穆妹纸串口调试
      *
      ********************************************************************
      **/
    
    
    #ifndef __SERIAL_H__
    #define __SERIAL_H__
    
    #ifdef __cplusplus
      extern "C" {
    #endif
    
    void serial_init(void);
    
    
    #ifdef __cplusplus    
      }
    #endif
    
    #endif   
    串口调试头 Serial.h
  • 相关阅读:
    快手视频下载脚本
    ffmpeg 加载双语字幕
    GNU Wget 1.19.1 static built on mingw32
    Struts配置应用2
    Struts配置应用1
    spring-IOC控制反转
    spring-纯pojo切面
    spring面向切面编程的方式实现
    spring-CGLib动态代理
    spring-JDK_AOP动态代理
  • 原文地址:https://www.cnblogs.com/gleam/p/3954220.html
Copyright © 2011-2022 走看看