新手上路
- 积分
- 40
- 金钱
- 40
- 注册时间
- 2020-3-19
- 在线时间
- 9 小时
|
通常情况下写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位 *
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));
}
}
|
|