OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 2598|回复: 1

STM32F407裸板uart驱动出现了乱码的问题

[复制链接]

4

主题

6

帖子

0

精华

新手上路

积分
40
金钱
40
注册时间
2020-3-19
在线时间
9 小时
发表于 2020-4-3 22:26:56 | 显示全部楼层 |阅读模式
通常情况下写stm32串口驱动都是用封装好的库去配置。今天写了个寄存器版本,出现了串口接收乱码问题,调了好久依然无果。网上查了好多资料都是库函数版本的串口驱动程序。

先说下功能,下位机等待上位机发来的数据,接收到数据后再发回到上位机,上位机收到后打印输出。上位机使用XCOM V2.3串口调试工具。
使用PA9,PA10作为uart转USB_232


先上代码
define.h头文件里就是定义了一个uint8_t类型为unsigned char


#include "define.h"
/*GPIOA基地址*/



#define                GPIOA_MODE                        (*(uint32_t *)0x40020000)        //GPIOA模式                        *
#define                GPIOA_ALTERNATE                 (*(uint32_t *)0x40020024)        //GPIOA复用功能                *
#define                GPIOA_RCC                        (*(uint32_t *)0x40023830)        //GPIOA外设时钟                *
#define                GPIOA_TYPE                        (*(uint32_t *)0x40023804)        //GPIOA输出类型                *
#define                GPIOA_SPEED                        (*(uint32_t *)0x40023808)        //GPIOA输出速度                *
#define                GPIOA_PUPD                        (*(uint32_t *)0x4002380C)        //GPIOA上下拉

/*uart1基地址0x40011000, 总线为APB2  时钟为84Mhz */



#define                UART1_RCC                        (*(uint32_t *)0x40023844)        //UART1外设时钟                *
#define                UART1_CONTROL_REG1        (*(uint32_t *)0x4001100c)        //UART1控制寄存器1
#define                UART1_CONTROL_REG2        (*(uint32_t *)0x40011010)        //UART1控制寄存器2
#define                UART1_CONTROL_REG3        (*(uint32_t *)0x40011014)        //UART1控制寄存器3
#define                UART1_BRR                        (*(uint32_t *)0x40011008)        //UART1波特率寄存器         *
#define                UART1_DATA_REG                (*(uint32_t *)0x40011004)        //UART1数据寄存器       
#define                UART1_STATUS_REG        (*(uint32_t *)0x40011000)        //UART1状态寄存器               



int main(void){               

        uint8_t resdata;               //数据缓冲区


        
        GPIOA_RCC &= ~(1);
        GPIOA_RCC |= (1);                                        //使能GPIOA外设时钟                *

        
        UART1_RCC &= ~(1 << 4);
        UART1_RCC |= (1 << 4);                                //使能UART1外设时钟                *
       
        
        GPIOA_MODE &= ~(3 << 18);
        GPIOA_MODE |= (2 << 18);                        //设置PA9为复用模式                *
        GPIOA_MODE &= ~(3 << 20);
        GPIOA_MODE |= (2 << 20);                        //配置PA10为复用模式                *
       
        
        GPIOA_TYPE &= ~(1 << 9);                        //配置PA9为推挽模式                *
        GPIOA_TYPE &= ~(1 << 10);                        //配置PA10为推挽模式                *
       
        
        GPIOA_SPEED &= ~(3 << 18);
        GPIOA_SPEED |= (2 << 18);                        //设置PA9输出速度为50mhz                *
        GPIOA_SPEED &= ~(3 << 20);
        GPIOA_SPEED |= (2 << 20);                        //设置PA10输出速度为50mhz                *
       
        
        GPIOA_PUPD &= ~(3 << 18);
        GPIOA_PUPD |= (1 << 18);                        //设置PA9为上拉电阻                *
        GPIOA_PUPD &= ~(3 << 20);
        GPIOA_PUPD |= (1 << 20);                        //设置PA10为上拉电阻                *
       
        
        GPIOA_ALTERNATE &= ~(15 << 4);
        GPIOA_ALTERNATE |= (7 << 4);                //配置PA9为复用功能                *
        GPIOA_ALTERNATE &= ~(15 << 8);
        GPIOA_ALTERNATE |= (7 << 8);                //配置PA10为复用功能                *
       
      
        
        UART1_BRR &= ~(0xFFFF);
        UART1_BRR |= (0x2d << 4);                        //84000000/8*(2-OVER8)*115200 = 45.563                *
        UART1_BRR |= (0x9);                                        //配置UART1发送速率
       

       // 下面为UART1控制寄存器1的配置
       
        UART1_CONTROL_REG1 &= ~(1 << 15);        //设置UART1过采样为16倍,0:16倍                1:8倍
       
        
        UART1_CONTROL_REG1 &= ~(1 << 13);               
        UART1_CONTROL_REG1 |= (1 << 13);        //使能UART1预分频 0:禁止                1:使能                *

      
        UART1_CONTROL_REG1 &= ~(1 << 12);        //设置UART1数据传输长度        0:8位                1:9位                *
                               
         QQ截图20200403202857.png
        UART1_CONTROL_REG1 &= ~(1 << 10);        //设置UART1奇偶校验位 0:禁止        1:使能                        *
       
        
        UART1_CONTROL_REG1 &= ~(1 << 3);                                       
        UART1_CONTROL_REG1 |= (1 << 3);                //设置UART1发送器        0:禁止                1:使能                        *
                                               
        
        UART1_CONTROL_REG1 &= ~(1 << 2);
        UART1_CONTROL_REG1 |= (1 << 2);                //设置UART1接收器        0:禁止                1:使能接收并搜索起始位        *

        //下面为UART1控制寄存器2的配置
      
        UART1_CONTROL_REG2 &= ~(3 << 12);        /*设置UART1停止位位数
                                                                                        00:1个停止位               
                                                                                        01:0.5个停止位                                *
                                                                                        10:2个停止位       
                                                                                        11:1.5个停止位        */

       
       
        //下面为UART1控制寄存器3的配置
        //由于未使用终端和DMA等相关配置所以控制寄存器3全部清0
        //到此初始化完成
        UART1_CONTROL_REG3 &= 0x0000;        //CTS中断使能位                0:禁止中断                *       
       
       

        //下面开始轮训接收数据,再发送回上位机并打印输出
        while(1){
               
                while(!(UART1_STATUS_REG & 0x10));          //检测是否有数据到来
                resdata = UART1_DATA_REG;                       //把接收到的数据放入缓冲区
                UART1_DATA_REG = resdata;                       //把接收到的数据放到发送寄存器,并发出
               
                while(!(UART1_STATUS_REG & 0x20));              //检测是否发送完毕
        }
       
}

测试有数据发送,并且传回,就是乱码。






再把整个代码发送一遍,方便整体观看。



#include "define.h"

#define                GPIOA_MODE                        (*(uint32_t *)0x40020000)        //GPIOA模式                        *
#define                GPIOA_ALTERNATE         (*(uint32_t *)0x40020024)        //GPIOA复用功能                *
#define                GPIOA_RCC                        (*(uint32_t *)0x40023830)        //GPIOA外设时钟                *
#define                GPIOA_TYPE                        (*(uint32_t *)0x40023804)        //GPIOA输出类型                *
#define                GPIOA_SPEED                        (*(uint32_t *)0x40023808)        //GPIOA输出速度                *
#define                GPIOA_PUPD                        (*(uint32_t *)0x4002380C)        //GPIOA上下拉
       
#define                UART1_RCC                        (*(uint32_t *)0x40023844)        //UART1外设时钟                *
#define                UART1_CONTROL_REG1        (*(uint32_t *)0x4001100c)        //UART1控制寄存器1
#define                UART1_CONTROL_REG2        (*(uint32_t *)0x40011010)        //UART1控制寄存器2
#define                UART1_CONTROL_REG3        (*(uint32_t *)0x40011014)        //UART1控制寄存器3
#define                UART1_BRR                        (*(uint32_t *)0x40011008)        //UART1波特率寄存器         *
#define                UART1_DATA_REG                (*(uint32_t *)0x40011004)        //UART1数据寄存器       
#define                UART1_STATUS_REG        (*(uint32_t *)0x40011000)        //UART1状态寄存器               



int main(void){               

        uint8_t resdata;
       
        GPIOA_RCC &= ~(1);
        GPIOA_RCC |= (1);                                        //使能GPIOA外设时钟                *
       
        UART1_RCC &= ~(1 << 4);
        UART1_RCC |= (1 << 4);                                //使能UART1外设时钟                *
       
        GPIOA_MODE &= ~(3 << 18);
        GPIOA_MODE |= (2 << 18);                        //设置PA9为复用模式                *
        GPIOA_MODE &= ~(3 << 20);
        GPIOA_MODE |= (2 << 20);                        //配置PA10为复用模式                *
       
        GPIOA_TYPE &= ~(1 << 9);                        //配置PA9为推挽模式                *
        GPIOA_TYPE &= ~(1 << 10);                        //配置PA10为推挽模式                *
       
        GPIOA_SPEED &= ~(3 << 18);
        GPIOA_SPEED |= (2 << 18);                        //设置PA9输出速度为50mhz                *
        GPIOA_SPEED &= ~(3 << 20);
        GPIOA_SPEED |= (2 << 20);                        //设置PA10输出速度为50mhz                *
       
        GPIOA_PUPD &= ~(3 << 18);
        GPIOA_PUPD |= (1 << 18);                        //设置PA9为上拉电阻                *
        GPIOA_PUPD &= ~(3 << 20);
        GPIOA_PUPD |= (1 << 20);                        //设置PA10为上拉电阻                *
       
        GPIOA_ALTERNATE &= ~(15 << 4);
        GPIOA_ALTERNATE |= (7 << 4);                //配置PA9为复用功能                *
        GPIOA_ALTERNATE &= ~(15 << 8);
        GPIOA_ALTERNATE |= (7 << 8);                //配置PA10为复用功能                *
       
        UART1_BRR &= ~(0xFFFF);
        UART1_BRR |= (0x2d << 4);                        //84000000/8*(2-OVER8)*115200 = 45.563                *
        UART1_BRR |= (0x9);                                        //配置UART1发送速率
       
        //UART1控制寄存器1
        UART1_CONTROL_REG1 &= ~(1 << 15);        //设置UART1过采样为16倍,0:16倍                1:8倍
       
        UART1_CONTROL_REG1 &= ~(1 << 13);               
        UART1_CONTROL_REG1 |= (1 << 13);        //使能UART1预分频 0:禁止                1:使能                *

        UART1_CONTROL_REG1 &= ~(1 << 12);        //设置UART1数据传输长度        0:8位                1:9位                *
                               
        UART1_CONTROL_REG1 &= ~(1 << 10);        //设置UART1奇偶校验位 0:禁止        1:使能                        *
       
        UART1_CONTROL_REG1 &= ~(1 << 3);                                       
        UART1_CONTROL_REG1 |= (1 << 3);                //设置UART1发送器        0:禁止                1:使能                        *
                                               
        UART1_CONTROL_REG1 &= ~(1 << 2);
        UART1_CONTROL_REG1 |= (1 << 2);                //设置UART1接收器        0:禁止                1:使能接收并搜索起始位        *

        //UART1控制寄存器2
        UART1_CONTROL_REG2 &= ~(3 << 12);        /*设置UART1停止位位数
                                                                                        00:1个停止位               
                                                                                        01:0.5个停止位                                *
                                                                                        10:2个停止位       
                                                                                        11:1.5个停止位        */


        //UART1控制寄存器3
        UART1_CONTROL_REG3 &= 0x0000;        //CTS中断使能位                0:禁止中断                *       
       
       
        while(1){
                while(!(UART1_STATUS_REG & 0x010));
                resdata = UART1_DATA_REG;
                UART1_DATA_REG = resdata;
                while(!(UART1_STATUS_REG & 0x020));       
        }
       
}


正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

4

主题

6

帖子

0

精华

新手上路

积分
40
金钱
40
注册时间
2020-3-19
在线时间
9 小时
 楼主| 发表于 2020-4-3 22:32:20 | 显示全部楼层
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-2 23:02

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表