本次主要体验CW32饭盒派开发板的串口功能。下面就分享一下串口的发送接收。
首先参考例子实现串口的初始化:使用PA9和PA10端口,这2个端口看了一下和别家的MCU不同,别人家的都是对应UART1,而本次的CW32饭盒派开发板MCU对应的是UART3。如下图所示,复用功能AF1对应UART3。
下面就是串口的初始化了。初始化UART3使用中断接收数据。
void UART_Configuration(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);
GPIO_InitStructure.Pins = GPIO_PIN_9;
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;
GPIO_InitStructure.Mode = GPIO_MODE_INPUT_PULLUP;
GPIO_Init(CW_GPIOA, &GPIO_InitStructure);
PA09_AFx_UART3TXD();
PA10_AFx_UART3RXD();
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);
USART_ITConfig(CW_UART3, USART_IT_RC, ENABLE);
NVIC_SetPriority(UART3_IRQn, 0);
NVIC_EnableIRQ(UART3_IRQn);
}
勾选KEIL的MicroLib,然后实现如下函数int fputc(int ch,FILE *f),就可以使用printf函数输出。
int stdout_putchar (int ch)
{
USART_SendData_8bit(CW_UART3, (uint8_t)ch);
while (USART_GetFlagStatus(CW_UART3, USART_FLAG_TXE) == RESET);
return ch;
}
int fputc(int ch,FILE *f)
{
return stdout_putchar(ch);
}
下面使用fifo接收数据。
typedef struct fifo_buffer
{
uint8_t buff[128];
volatile uint32_t read_i;
volatile uint32_t write_i;
}fifo_buffer;
fifo_buffer shell_uart_rx=
{
.read_i = 0,
.write_i = 0,
};
void UART3_IRQHandler(void)
{
unsigned char TxRxBuffer;
if(USART_GetITStatus(CW_UART3, USART_IT_RC) != RESET)
{
USART_ClearITPendingBit(CW_UART3, USART_IT_RC);
if(((shell_uart_rx.write_i+1)&0x7f) != shell_uart_rx.read_i)
{
shell_uart_rx.buff[shell_uart_rx.write_i++] = USART_ReceiveData_8bit(CW_UART3);
shell_uart_rx.write_i &= 0x7f;
}
}
}
这样串口的发送和接收都搞定了。下面就利用串口移植一个shell功能测试一下。
本次就选用了nr_micro_shell这一个开源的shell库。这个简单方便,用的也挺多的。其实听说还有个letter_shell可以支持权限管理,后面再研究一下。
首先下载这个nr_micro_shell库,然后添加到keil工程内。
然后配置一下nr_micro_shell功能,如下图所示。再就是配置串口的输出。
在main中初始化shell和接收串口数据。代码如下:
int main(void)
{
RCC_Configuration();
SysTick_Config(SystemCoreClock/1000);
UART_Configuration();
GPIO_Configuration(CW_GPIOA, GPIO_PIN_7 | GPIO_PIN_8, 0x3);
printf("uart test out\r\n");
shell_init();
while (1)
{
if(shell_uart_rx.read_i != shell_uart_rx.write_i)
{
shell(shell_uart_rx.buff[shell_uart_rx.read_i++]);
shell_uart_rx.read_i &= 0x7f;
}
}
}
shell自带2个命令例子,一个ls,一个test。
下面我就自己再实现一个led灯控制命令。
代码如下:
void shell_led_cmd(char argc, char *argv)
{
if (argc > 1)
{
if (!strcmp("on", &argv[argv[1]]))
{
if (!strcmp("1", &argv[argv[2]]))
{
GPIO_WritePin(CW_GPIOA, GPIO_PIN_7, GPIO_Pin_RESET);
printf("led 1 on.\r\n");
return ;
}else if (!strcmp("2", &argv[argv[2]]))
{
GPIO_WritePin(CW_GPIOA, GPIO_PIN_8, GPIO_Pin_RESET);
printf("led 2 on.\r\n");
return ;
}
}else if (!strcmp("off", &argv[argv[1]]))
{
if (!strcmp("1", &argv[argv[2]]))
{
GPIO_WritePin(CW_GPIOA, GPIO_PIN_7, GPIO_Pin_SET);
printf("led 1 off.\r\n");
return ;
}else if (!strcmp("2", &argv[argv[2]]))
{
GPIO_WritePin(CW_GPIOA, GPIO_PIN_8, GPIO_Pin_SET);
printf("led 2 off.\r\n");
return ;
}
}
}
printf("usage: led [on/off] [1/2]\r\n");
}
NR_SHELL_CMD_EXPORT(led, shell_led_cmd, "led ctrl");
下面就是上一个USB转串口接开发板上MCU的PA9和PA10脚。
一切就绪,下面就来试试效果吧。编译下载一通搞定成功。
用putty打开串口。首先测试一下shell自带的命令效果。
下面测试自己写的led灯控制命令。