芯源半导体CW32
直播中

hehung

8年用户 659经验值
擅长:嵌入式技术
私信 关注

【CW32饭盒派开发板试用体验】2. 使用扩展板串口UART3以及scanf重定向到串口

【CW32饭盒派开发板试用体验】1. 开箱啦

前言

官方例程提供了对串口的支持,但是默认代码使用的是UART1,扩展板引出来的引脚是UART3,所以修改官方提供的代码为UART1。官方已经实现了对串口重定向到printf的支持,本文将增加串口对scanf的重定向支持。

USB-TTL串口使用了Wch-Link上的串口。

官方资料下载:点我下载资料

这里需要注意一点的是,下载了elecfans提供的资料之后,需要详细看《CW32系列微控制器软件开发工具入门.pdf》,了解MDK上开发的一些注意事项。过程相对而言比较繁琐,因为没有提供CW32配套的pack包,所以如果需要正常下载是需要进行一些特殊配置的,本文就不做赘述了。

1 硬件连接

我们可以看到扩展板引出来的串口是 串口1,其实是UART3。

可以看到串口1所连接的引脚是PA9和PA10,我们可以查询数据手册看一下具体的复用关系。
1685263948042.png

扩展板串口的硬件原理图如下:
1685264060891.png

查看硬件数据手册,可以直到PA9和PA10是连接到了UART3上面的。复用功能1。
1685263911108.png

2 软件开发

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;
}

3 实现结果

见下图,可以看到,成功重定向了scanf到串口接收。后续就可以使用scanf来接收一些控制命令做调试了。
1685263606416.png

更多回帖

发帖
×
20
完善资料,
赚取积分