官方例程提供了对串口的支持,但是默认代码使用的是UART1,扩展板引出来的引脚是UART3,所以修改官方提供的代码为UART1。官方已经实现了对串口重定向到printf的支持,本文将增加串口对scanf的重定向支持。
USB-TTL串口使用了Wch-Link上的串口。
官方资料下载:点我下载资料
这里需要注意一点的是,下载了elecfans提供的资料之后,需要详细看《CW32系列微控制器软件开发工具入门.pdf》,了解MDK上开发的一些注意事项。过程相对而言比较繁琐,因为没有提供CW32配套的pack包,所以如果需要正常下载是需要进行一些特殊配置的,本文就不做赘述了。
我们可以看到扩展板引出来的串口是 串口1
,其实是UART3。
可以看到串口1所连接的引脚是PA9和PA10,我们可以查询数据手册看一下具体的复用关系。
扩展板串口的硬件原理图如下:
查看硬件数据手册,可以直到PA9和PA10是连接到了UART3上面的。复用功能1。
UART3和UART1使用的一些函数有区别,不是简单的替换就可以使用的,详见下面的代码,对于scanf的实现,使用了接收中断。
/*
@hehung
2023-5-28
email: 1398660197@qq.com
wechat: hehung95
reproduced and please indicate the source @hehung
*/
#include "main.h"
void GPIO_Configuration(void);
void RCC_Configuration(void);
void UART_init(void);
void BTIM_init(void);
unsigned int counttime=0;
typedef struct
{
boolean_t recv_flag;
uint8_t data;
} uart_recv_t;
uart_recv_t uart3_recv_sta;
int main()
{
uint16_t t=0;
RCC_Configuration(); //系统时钟64M
GPIO_Configuration(); //LED初始化
UART_init(); //串口初始化
BTIM_init(); //定时器初始化
printf ("This is a UART TEST for CW32F030\\r\\n");
printf ("Please input a number with int type\\r\\n");
int a;
scanf ("%d", &a);
printf ("The number you input is: %d\\r\\n", a);
while(1)
{
}
}
void UART_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APBPeriphClk_Enable1(RCC_APB1_PERIPH_UART3, ENABLE);
RCC_AHBPeriphClk_Enable( RCC_AHB_PERIPH_GPIOA, ENABLE);
PA09_AFx_UART3TXD();
PA10_AFx_UART3RXD();
GPIO_InitStructure.Pins = GPIO_PIN_9; //PA9
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
GPIO_Init(CW_GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.Pins = GPIO_PIN_10; //PA10
GPIO_InitStructure.Mode = GPIO_MODE_INPUT_PULLUP;
GPIO_Init(CW_GPIOA, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_Over = USART_Over_16;
USART_InitStructure.USART_Source = USART_Source_PCLK;
USART_InitStructure.USART_UclkFreq = 64000000;
USART_InitStructure.USART_StartBit = USART_StartBit_FE;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No ;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(CW_UART3, &USART_InitStructure);
//使能UARTx RC中断
USART_ITConfig(CW_UART3, USART_IT_RC, ENABLE);
//优先级,无优先级分组
NVIC_SetPriority(UART3_IRQn, 0);
//UARTx中断使能
NVIC_EnableIRQ(UART3_IRQn);
}
void UART3_IRQHandler(void)
{
if(USART_GetITStatus(CW_UART3, USART_IT_RC) != RESET)
{
USART_ClearITPendingBit(CW_UART3, USART_IT_RC);
uart3_recv_sta.data = USART_ReceiveData_8bit(CW_UART3);
uart3_recv_sta.recv_flag = TRUE;
}
}
void RCC_Configuration(void)
{
/* 0. HSI使能并校准 */
RCC_HSI_Enable(RCC_HSIOSC_DIV6);
/* 1. 设置HCLK和PCLK的分频系数 */
RCC_HCLKPRS_Config(RCC_HCLK_DIV1);
RCC_PCLKPRS_Config(RCC_PCLK_DIV1);
/* 2. 使能PLL,通过PLL倍频到64MHz */
RCC_PLL_Enable(RCC_PLLSOURCE_HSI, 8000000, 8); // HSI 默认输出频率8MHz
// RCC_PLL_OUT(); //PC13脚输出PLL时钟
///< 当使用的时钟源HCLK大于24M,小于等于48MHz:设置FLASH 读等待周期为2 cycle
///< 当使用的时钟源HCLK大于48MHz:设置FLASH 读等待周期为3 cycle
__RCC_FLASH_CLK_ENABLE();
FLASH_SetLatency(FLASH_Latency_3);
/* 3. 时钟切换到PLL */
RCC_SysClk_Switch(RCC_SYSCLKSRC_PLL);
RCC_SystemCoreClockUpdate(64000000);
}
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
__RCC_GPIOA_CLK_ENABLE();
__RCC_GPIOC_CLK_ENABLE();
GPIO_InitStruct.IT = GPIO_IT_NONE; //LED2
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pins = GPIO_PIN_7;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_Init(CW_GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pins = GPIO_PIN_13; //LED4
GPIO_Init(CW_GPIOC,&GPIO_InitStruct);
GPIO_WritePin(CW_GPIOA,GPIO_PIN_7,GPIO_Pin_RESET);
GPIO_WritePin(CW_GPIOC,GPIO_PIN_13,GPIO_Pin_RESET);
}
void BTIM_init(void)
{
BTIM_TimeBaseInitTypeDef BTIM_InitStruct;
__RCC_BTIM_CLK_ENABLE();
__disable_irq();
NVIC_EnableIRQ(BTIM1_IRQn);
__enable_irq();
BTIM_InitStruct.BTIM_Mode = BTIM_Mode_TIMER;
BTIM_InitStruct.BTIM_OPMode = BTIM_OPMode_Repetitive;
BTIM_InitStruct.BTIM_Period = 8000;
BTIM_InitStruct.BTIM_Prescaler = BTIM_PRS_DIV8;
BTIM_TimeBaseInit(CW_BTIM1, &BTIM_InitStruct);
BTIM_ITConfig(CW_BTIM1, BTIM_IT_OV, ENABLE);
BTIM_Cmd(CW_BTIM1, ENABLE);
}
void BTIM1_IRQHandler(void)
{
/* USER CODE BEGIN */
static unsigned int count2=0;
if(BTIM_GetITStatus(CW_BTIM1, BTIM_IT_OV))
{
BTIM_ClearITPendingBit(CW_BTIM1, BTIM_IT_OV);
count2++;
counttime++;
if(count2>=500)//0.5S
{
count2=0;
PA07_TOG();
}
}
/* USER CODE END */
}
int fputc(int ch, FILE *f)
{
(void)f;
USART_SendData_8bit(CW_UART3, (uint8_t)ch);
while (USART_GetFlagStatus(CW_UART3, USART_FLAG_TXE) == RESET) {};
return ch;
}
int fgetc(FILE *f)
{
(void)f;
while (FALSE == uart3_recv_sta.recv_flag) {};
uart3_recv_sta.recv_flag = FALSE;
return (int)uart3_recv_sta.data;
}
见下图,可以看到,成功重定向了scanf到串口接收。后续就可以使用scanf来接收一些控制命令做调试了。
更多回帖