【前言】
GD32H759拥有最多8个通用同步异步收发器(USART),其中USART0、USART5是挂载在APB2总线上,而其余6个是挂载在APB1总线之上。具体见下如:
根据开发板原理图,USART0通过PA9、PA10的端口接到了板载的CH340上面,可以用来打印参数等。其原理图如下:
因此,从USART0进行试用。
【工程以及具体配置】
1、在工程中,在bsp下面新建uart.h、uart.c,用于uart的业务。
由于要开启UART总线时钟,在lugl_gd32h7xx.h头文件中定时RCU_APB2EN的地址:
- //APB2EN 串口挂载在 APB2 使能寄存器(RCU_APB2EN)偏移 0x44
- #define LU_RCU_APB2EN (*(volatile uint32_t *)(uint32_t)(0x58024444))
3、在PIN9、PIN10,备用选择寄存器为GPIOx_AFSEL1,偏移地址为:0x24,因此在lugl_gd32h7xx.h中定义:
#define LU_GPIOA_AFSEL1 (*(volatile uint32_t *)(uint32_t)0x58020024)
配置为:
- //配置 GPIOA9、10复用模式。为输出高速上拉,
- LU_GPIOA_AFSEL1 &= ~((uint32_t)0b1111<<4);
- LU_GPIOA_AFSEL1 |= ((uint32_t)0b0111<<4);
-
- LU_GPIOA_AFSEL1 &= ~((uint32_t)0b1111<<8);
- LU_GPIOA_AFSEL1 |= ((uint32_t)0b0111<<8);
//APB2EN 串口挂载在 APB2 使能寄存器(RCU_APB2EN)偏移 0x44
#define LU_RCU_APB2EN (*(volatile uint32_t *)(uint32_t)(0x58024444))
- //打开USART0总线时钟
- LU_RCU_APB2EN |= ((uint32_t)0x01 << 4);
然后配置GPIO的AF复用,PA9 为推挽输出,上拉,60M速度
- LU_GPIOA_CTL &= ~((uint32_t)0b11<<(2U*9));
- LU_GPIOA_CTL |= ((uint32_t)0b10<<(2U*9)); //10
- LU_GPIOA_OMODE &= ~((uint32_t)0x01<<9); //0输出模式 输出推挽模式(复位值)
- LU_GPIOA_OSPD &= ~((uint32_t)0b11<<(2U*9)); //清零
- LU_GPIOA_OSPD |= ((uint32_t)0b01<<(2U*9)); //01:输出最大速度60M
- LU_GPIOA_PUD &= ~((uint32_t)0b11<<(2U*9)); //清零
- LU_GPIOA_PUD |= ((uint32_t)0b01<<(2U*9)); //01:端口上拉模式
- LU_GPIOA_CTL &= ~((uint32_t)0b11<<(2U*10)); //
- LU_GPIOA_CTL |= ((uint32_t)0b10<<(2U*9));
- LU_GPIOA_OSPD &= ~((uint32_t)0b11<<(2U*9)); //清零
- LU_GPIOA_OSPD |= ((uint32_t)0b01<<(2U*9)); //01:最大速度60M
- LU_GPIOA_PUD &= ~((uint32_t)0b11<<(2U*9)); //清零
- LU_GPIOA_PUD |= ((uint32_t)0b01<<(2U*9)); //01:端口上拉模式
1)首先重置USART0,经学习官方示例,他就是先开启睡眠模式,然后关闭,代码如下:
- /* 关闭睡眠时钟使能 USART0SPEN 在睡眠模式下 USART0 时钟使能
- 由软件置位或复位
- 0:关闭在睡眠模式下 USART0 时钟
- 1:开启在睡眠模式下 USART0 时钟
- 4bit
- */
- LU_RCU_ADDAPB2SPEN |= ((uint32_t)0x01<<4U);
- LU_RCU_ADDAPB2SPEN &= ~((uint32_t)0x01<<4U);
- /* 关闭USART */
- /*
- USART使能
- 0:USART预分频器和输出禁用
- 1:USART预分频器和输出被使能
- */
- LU_USART0_CTL0 &= ~((uint32_t)0x01<<0);
因此我位配置代码如下:
- LU_USART0_CTL0 &= ~(((uint32_t)0x01<<12) | ((uint32_t)0x01<<28)); //定义为00 即8数据位
- /* configure USART word length */
- LU_USART0_CTL0 |= (((uint32_t)0x00<<12) | ((uint32_t)0x00<<28)); //8bit为00
我们配置为1位停止位时,给这两个BIT写0x00,代码如下:
- LU_USART0_CTL1 &= ~((uint32_t)0b11<<12); //请除【13:12】位 STB
- LU_USART0_CTL1 |= ((uint32_t)0b00<<12); // STOP位长 00:1停止位
- //设置波特率 这里定为115200 总线频率为300M,先不计算先,写死0x00000A2C
- LU_USART0_BAUD = 0x00000A2C;
- LU_USART0_CTL0 &= ~((uint32_t)0x01<<2); //先清除REN 位
- LU_USART0_CTL0 |= ((uint32_t)0x01<<2); //接收使能
-
- LU_USART0_CTL0 &= ~((uint32_t)0x01<<3); //先清除REN 位
- LU_USART0_CTL0 |= ((uint32_t)0x01<<3); //接收使能
- LU_USART0_CTL0 |= 0x01; //1:USART预分频器和输出被使能
5、接着编写串口阻塞式的发送一个Byte的函数,非常简单,就是往USART0_TDATA的[9:0]位写入需要发送的数据就行了。
- void usart0_data_transmit(uint16_t data)
- {
- LU_USART0_TDATA = ((uint32_t)0x3FF & (uint32_t)data); //0-9位
- }
- /* retarget the C library printf function to the USART */
- int fputc(int ch, FILE *f)
- {
- usart0_data_transmit((uint8_t)ch);
- while(RESET == ((LU_USART0_STAT >>6) & 0x01));
- return ch;
- }
【实现效果】
当然配置好后,需要进行验证,在TobudOS的工程中,添加uart.c进来,并在任务中添回printf,其任务函数如下:
- void test_task(void *Parameter)
- {
- while(1)
- {
- TG_LED1;
- printf("\r\ntask1\r\n\r\n");
- tos_task_delay(2000);
- }
- }
- void led_task_entry(void *Parameter)
- {
- while(1)
- {
- TG_LED2;
- printf("\r\ntask2\r\n\r\n");
- tos_task_delay(500);
-
- }
-
- }
【总结】
经过一天的学习,熟悉了USART0的几个普通寄存器,以及相关的配置与应用,并成功的编写好了应用,实现了printf。
使用寄存器配置,相比库函数,代码要简洁,运行速度也要快!
附:基于TobudOS的工程源码:
热门活动
全部回复 0
暂无评论,快来抢沙发吧