这块板子的串口比较粗暴,是直接引出至232,使用的max3232进行转接的。
使用的板载串口为USART0,从原理图可以看到接的是PA9和PA10。
(一)时钟
串口初始化首先要使能时钟:
包括GPIO时钟和串口外设时钟:
/* enable GPIO clock */
rcu_periph_clock_enable(RCU_GPIOA);
/* enable USART clock */
rcu_periph_clock_enable(RCU_USART0);
关于时钟源,参考手册提到
“由外设时钟分频产生,其中USART0/5由PCLK2分频得到,USART1/2和
UART3/4/6/7由PCLK1分频得到;”
PCLK1并非指某一个总线,而是每个外设自己的时钟,
rcu_periph_clock_enable(RCU_USART0);
即为USART专属的PCLK开关。
但前方的APB2还是需要使能的。但这部分在系统初始化处使能了。
首先我们看startup_gd32f450.s文件。
在初始化调用main之前调用了 SystemInit 函数。
里面又调用了一个
system_clock_config();
再往里面调用了:
system_clock_200m_25m_hxtal();
函数:
static void system_clock_200m_25m_hxtal(void)
{
uint32_t timeout = 0U;
uint32_t stab_flag = 0U;
/* enable HXTAL */
RCU_CTL |= RCU_CTL_HXTALEN;
/* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
do{
timeout++;
stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
}while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
/* if fail */
if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
while(1){
}
}
RCU_APB1EN |= RCU_APB1EN_PMUEN;
PMU_CTL |= PMU_CTL_LDOVS;
/* HXTAL is stable */
/* AHB = SYSCLK */
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
/* APB2 = AHB/2 */
RCU_CFG0 |= RCU_APB2_CKAHB_DIV2;
/* APB1 = AHB/4 */
RCU_CFG0 |= RCU_APB1_CKAHB_DIV4;
/* Configure the main PLL, PSC = 25, PLL_N = 400, PLL_P = 2, PLL_Q = 9 */
RCU_PLL = (25U | (400U << 6U) | (((2U >> 1U) - 1U) << 16U) |
(RCU_PLLSRC_HXTAL) | (9U << 24U));
/* enable PLL */
RCU_CTL |= RCU_CTL_PLLEN;
/* wait until PLL is stable */
while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
}
/* Enable the high-drive to extend the clock frequency to 200 Mhz */
PMU_CTL |= PMU_CTL_HDEN;
while(0U == (PMU_CS & PMU_CS_HDRF)){
}
/* select the high-drive mode */
PMU_CTL |= PMU_CTL_HDS;
while(0U == (PMU_CS & PMU_CS_HDSRF)){
}
/* select PLL as system clock */
RCU_CFG0 &= ~RCU_CFG0_SCS;
RCU_CFG0 |= RCU_CKSYSSRC_PLLP;
/* wait until PLL is selected as system clock */
while(0U == (RCU_CFG0 & RCU_SCSS_PLLP)){
}
}
这个函数对APB2进行了初始化。
(二)设置GPIO功能以及重映射
相关映射功能查阅数据手册
映射到AF7,设置GPIO上下拉等功能。
// configure the USART0 Tx pin and USART0 Rx pin
gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_9);
gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_10);
// configure USART0 Tx as alternate function push-pull
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_9);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);
// configure USART0 Rx as alternate function push-pull
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_10);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_10);
(三)配置USART
/* USART configure */
usart_deinit(USART0);
usart_baudrate_set(USART0, 115200U);
usart_receive_config(USART0, USART_RECEIVE_ENABLE);
usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);
usart_enable(USART0);
这个配置先不去深究,首先能够进行基本的收发再说,后面有机会搞DMA收发再详究寄存器。
(四)发送
编写一个发送函数:
void PRINTF_UART0(char *data)
{
int i;
for(i=0;i<strlen(data);i++){
usart_data_transmit(USART0, data[i]);
while(RESET == usart_flag_get(USART0, USART_FLAG_TBE));
}
}
(五)硬件连接
板载只有一个232公头接口,相当麻烦,因为一般主机才会用公头接口,所以转串口线都是公头的,公头对公头无法连接。
恰逢放假,手上那条平时用开的母头对母头转接线不在身边。翻箱底找了很久,找了一条别的线,试了下竟然不行。
图中又是上逻辑分析仪又是上232转USB,所有收发都是没问题的。最后发现是这条转接线有问题!
一般的母头对母头转接线需要把RX和TX反过来,结果它是一对一接的,这下完犊子了,怎么办呢?这时候突然想起之前做的一块板子:
这里用的是一个比较便于实验的设计,打横和打竖接跳线码可以把TX和RX反过来。
主函数里轮询执行:
delay_ms(100);
PRINTF_UART0("welcome!\r\n");
效果:
|