本帖最后由 xyz549040622 于 2020-12-4 23:01 编辑
拿到一个开发板,在使得GPIO点亮LED闪烁成功,证明最小系统OK后,下一步要做的必然是打通USART接口,使得用户可以与开发板进行数据的交互。
MRS软件在自动创建工程后,会自动创建一个Debug的文件夹,里面包含Debug.c和Debug.h,这里面自动使能了USART1的串口功能,并使用了串口阻塞方式发送数据,并重定义了printf函数,使得程序中可以使用printf函数发送数据。
这里为了方便数据的交互,我们需要增加串口接收数据函数,使用阻塞方式发送数据,因此不使用官方的Debug.c中的函数,从而自己编写串口函数usart.c和usart.h。
友情提示,由于板子上国产SP232的影响,串口1TTL的接收是受影响的,必须把SP232拆掉才能使能串口1的接收,或者改为使用串口2、串口3的接收。如下图所示:
1.在workspace-RISC-V下新建一个文件夹CH32V103C8T6-USART1并将工程命名为CH32V103C8T6-USART1。
2.删除Debug里的关于串口的全部函数,只保留延时函数,把debug.h变为延时函数。
/********************************** (C) COPYRIGHT *******************************
* File Name : debug.c
* Author : WCH
* Version : V1.0.0
* Date : 2020/04/30
* Description : This file contains all the functions prototypes for UART
* Printf , Delay functions.
*******************************************************************************/
#include "delay.h"
static uint8_t p_us=0;
static uint16_t p_ms=0;
/*******************************************************************************
* Function Name : Delay_Init
* Description : Initializes Delay Funcation.
* Input : None
* Return : None
*******************************************************************************/
void Delay_Init(void)
{
p_us=SystemCoreClock/8000000;
p_ms=(uint16_t)p_us*1000;
}
/*******************************************************************************
* Function Name : Delay_Us
* Description : Microsecond Delay Time.
* Input : n:Microsecond number.
* Return : None
*******************************************************************************/
void Delay_Us(uint32_t n)
{
uint32_t i;
SysTick->CTLR = 0;
i = (uint32_t)n*p_us;
SysTick->CNTL0 = 0;
SysTick->CNTL1 = 0;
SysTick->CNTL2 = 0;
SysTick->CNTL3 = 0;
SysTick->CTLR = 1;
while((*(__IO uint32_t*)0xE000F004) <= i);
}
/*******************************************************************************
* Function Name : Delay_Ms
* Description : Millisecond Delay Time.
* Input : n:Millisecond number.
* Return : None
*******************************************************************************/
void Delay_Ms (uint32_t n)
{
uint32_t i;
SysTick->CTLR = 0;
i = (uint32_t)n*p_ms;
SysTick->CNTL0 = 0;
SysTick->CNTL1 = 0;
SysTick->CNTL2 = 0;
SysTick->CNTL3 = 0;
SysTick->CTLR = 1;
while((*(__IO uint32_t*)0xE000F004) <= i);
}
3.增加usart.c的串口函数,配置串口1,使能发送和接收功能
#include "usart.h"
/*******************************************************************************
* Function Name : USARTx_CFG
* Description : Initializes the USART2 peripheral.
* Input : None
* Return : None
*******************************************************************************/
void USART1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1, ENABLE); //使能GPIOA时钟
USART_DeInit(USART1);
/* USART2 TX-->A.2 RX-->A.3 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //设置PA9为复用功能
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //设置PA10为浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = 9600; //设置串口波特率为115200
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长为8位数据格式
USART_InitStructure.USART_StopBits = USART_StopBits_1; //1个停止位
USART_InitStructure.USART_Parity = USART_Parity_No; //无奇偶校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件流控制
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; //发送和接收模式
USART_Init(USART1, &USART_InitStructure); //初始化串口
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1; //抢占优先级为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //子优先级为1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //中断优先级初始化
USART_Cmd(USART1, ENABLE); //使能串口
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //开启中断
}
void USARTx_SendByte(USART_TypeDef* pUSARTx, uint8_t data)
{
USART_SendData(pUSARTx, data);
while(USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
}
void USARTx_SendStr(USART_TypeDef* pUSARTx, char *str)
{
uint8_t i = 0;
do
{
USARTx_SendByte(pUSARTx, *(str+i));
i++;
}while(*(str+i) != '\0');
while(USART_GetFlagStatus(pUSARTx, USART_FLAG_TC) == RESET);
}
4.添加led.c增加led的翻转闪烁函数
#include "led.h"
void User_Led_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
/* USART1 TX-->PA9 RX-->PA10 */
GPIO_InitStructure.GPIO_Pin = User_LED1_Pin|User_LED2_Pin;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(User_LED_Port, &GPIO_InitStructure);
GPIO_SetBits(User_LED_Port,User_LED1_Pin);
GPIO_SetBits(User_LED_Port,User_LED2_Pin);
}
void Toggle_User_Led(LED_LABEL LEDNAME)
{
if(LEDNAME == User_LED1)
{
if(GPIO_ReadOutputDataBit(User_LED_Port,User_LED1_Pin) == Bit_SET)
{
GPIO_ResetBits(User_LED_Port,User_LED1_Pin);
}
else
{
GPIO_SetBits(User_LED_Port,User_LED1_Pin);
}
}
else if(LEDNAME == User_LED2)
{
if(GPIO_ReadOutputDataBit(User_LED_Port,User_LED2_Pin) == Bit_SET)
{
GPIO_ResetBits(User_LED_Port,User_LED2_Pin);
}
else
{
GPIO_SetBits(User_LED_Port,User_LED2_Pin);
}
}
}
5.配置接收中断函数和main函数,接收到串口指令0x01后翻转LED1。
/********************************** (C) COPYRIGHT *******************************
* File Name : main.c
* Author : WCH
* Version : V1.0.0
* Date : 2020/04/30
* Description : Main program body.
*******************************************************************************/
/*
*@Note
串口打印调试例程:
USART1_Tx(PA9)。
本例程演示使用 USART1(PA9) 作打印调试口输出。
*/
#include "usart.h"
#include "led.h"
#include "../Delay/delay.h"
/* Global typedef */
/* Global define */
/* Global Variable */
void USART1_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
#define RxBufferSize 1
//定义一个字节的缓冲数组
volatile uint8_t RxBuffer[RxBufferSize]={0};
//接收OK标志
volatile uint8_t RxOK = 0;
/*******************************************************************************
* Function Name : USART2_IRQHandler
* Description : This function handles USART2 global interrupt request.
* Input : None
* Return : None
*******************************************************************************/
void USART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //中断产生
{
RxBuffer[0] = USART_ReceiveData(USART1); //接收数据
USART_ClearITPendingBit(USART1,USART_IT_RXNE); //清除中断标志
RxOK = 1;
USARTx_SendByte(USART1,0x01);
}
}
/*******************************************************************************
* Function Name : main
* Description : Main program.
* Input : None
* Return : None
*******************************************************************************/
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
Delay_Init();
User_Led_Init();
USART1_Init();
USARTx_SendStr(USART1, "This is a test data.\n");
while(1)
{
if(RxOK == 1)
{
if(RxBuffer[0] == 0x01)
{
Toggle_User_Led(User_LED1);
}
RxOK = 0;
}
}
}
将工程做了个打包,可以直接使用:
CH32V103-USART1.rar
(446.25 KB)
|