芯片资源介绍:
CH32V307系列是基于32位RISC-V设计的互联型微控制器,配备了硬件堆栈区、快速中断入口,在标准RISC-V基础上大大提高了中断响应速度。加入单精度浮点指令集,扩充堆栈区,具有更高的运算性能。扩展串口UART数量到8组,电机定时器到4组。提供USB2.0高速接口(480Mbps)并内置了PHY收发器,以太网MAC升级到千兆并集成了10M-PHY模块。
芯片框图:
芯片特点:
- 青稞V4F处理器,最高144MHz系统主频
- 支持单周期乘法和硬件除法,支持硬件浮点运算(FPU)
- 64KB SRAM,256KB Flash
- 供电电压:2.5/3.3V,GPIO单元独立供电
- 多种低功耗模式:睡眠、停止、待机
- 上/下电复位、可编程电压监测器
- 2组18路通用DMA
- 4组运放比较器
- 1个随机数发生器TRNG
- 2组12位DAC转换
- 2单元16通道12位ADC转换,16路触摸按键TouchKey
- 10组定时器
- USB2.0全速OTG接口
- USB2.0高速主机/设备接口(480Mbps 内置PHY)
- 3个USART接口和5个UART接口
- 2个CAN接口(2.0B主动)
- SDIO接口、FSMC接口、DVP数字图像接口
- 2组IIC接口、3组SPI接口、2组IIS接口
- 千兆以太网控制器ETH(内置10M PHY)
- 80个I/O口,可以映射到16外部中断
- CRC计算单元,96位芯片唯一ID
- 串行2线调试接口
- 封装形式:LQFP64M、LQFP100
八组串口包含 3 个通用同步异步收发器(USART1/2/3)和 5 个通用异步收发器(UART4/5/6/7/8);
串口的主要特征
- 全双工或半双工的同步或异步通信
- NRZ 数据格式
- 分数波特率发生器,最高 9Mbps
- 可编程数据长度
- 可配置的停止位
- 支持 LIN,IrDA 编码器,智能卡
- 支持 DMA
- 多种中断源
同步串口模式:
同步模式使得系统在使用 USART 模块时可以输出时钟信号。在开启同步模式对外发送数据时,CK 引脚会同时对外输出时钟。
开启同步模式的方式:
- 对控制寄存器 2(R16_USARTx_CTLR2)的 CLKEN 位置位;
- 同时需要关闭 LIN 模式、智能卡模式、红外模式和半双工模式;
- 也就是保证 SCEN、HDSEL 和 IREN 位处于复位状态,这三位在控制寄存器 3(R16_USARTx_CTLR3)中;
- 同步模式使用的要点在于时钟的输出控制。
有以下几点需要注意:
- USART 模块同步模式只工作在主模式,即 CK 引脚只输出时钟,不接收输入;
- 只在 TX 引脚输出数据时输出时钟信号;
- LBCL 位决定在发送最后一位数据位时是否输出时钟,CPOL 位决定时钟的极性,CPHA 决定时钟的 相位,这三个位在控制寄存器 2(R16_USARTx_CTLR2)中;
- 这三个位需要在 TE 和 RE 未被使能的情况下设置;
异步串口模式:
通用异步串口通信就是我们常见的串行通信方式,广泛用于嵌入式系统、传感器、外围设备等领域。它是异步串口通信的一种实现方式,采用起始位、数据位、停止位和校验位的组合来进行数据传输,而不依赖固定的时钟信号来同步数据。
与同步通信比它有一下特点:
- 简单性:通用异步串口通信相对于同步串口通信更简单,因为它不需要同步时钟信号,而是通过特定的起始位和停止位组合进行数据同步。
- 灵活性:异步串口通信支持不同的数据传输速率(波特率)和数据位长度,可以根据具体应用的需求进行灵活配置。
- 通用性:几乎所有的现代计算机和嵌入式系统都支持异步串口通信,使其成为一种广泛兼容的通信方式。
异步串口工作原理:
异步串口通信通过在每个字符的传输中添加起始位和停止位来同步数据。数据位是实际携带数据的位数,而校验位是可选的,用于验证数据的正确性。一般情况下,异步串口通信的数据帧由起始位 - 数据位 - 校验位(可选) - 停止位组成。数据发送端在传输数据前,先发送一个起始位,然后依次发送数据位的内容,校验位(如果使用)和停止位。接收端在接收数据时,根据起始位和停止位的边界来判断每个字符的开始和结束,并提取数据位的内容。如果使用了校验位,接收端将使用校验位来验证数据的正确性。异步串口通信通常需要在通信双方事先约定好波特率、数据位长度、校验位设置等参数,以确保数据能够正确地传输和解析。总的来说,通用异步串口通信是一种简单、灵活且广泛使用的串行通信方式,适用于各种嵌入式系统和外围设备之间的数据传输。
串口引脚:
LQFP100封装CH32V307VCT6默认串口引脚表格
芯片使用引脚 | 默认复用功能 | 功能解释 |
---|---|---|
PA9 | USART1_TX | 通用同步/异步1发送 |
PA10 | USART1_RX | 通用同步/异步1接收 |
PA2 | USART2_TX | 通用同步/异步2发送 |
PA3 | USART2_RX | 通用同步/异步2接收 |
PB10 | USART3_TX | 通用同步/异步3发送 |
PB11 | USART3_RX | 通用同步/异步3接收 |
PC10 | UART4_TX | 通用异步4发送 |
PC11 | UART4_RX | 通用异步4接收 |
PC12 | UART5_TX | 通用异步5发送 |
PD2 | UART5_RX | 通用异步5接收 |
PC0 | UART6_TX | 通用异步6发送 |
PC1 | UART6_RX | 通用异步6接收 |
PC2 | UART7_TX | 通用异步7发送 |
PC3 | UART7_RX | 通用异步7接收 |
PC4 | UART8_TX | 通用异步8发送 |
PC5 | UART8_TX | 通用异步8接收 |
串口示例代码:
void USART1_GPIO_Config(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStruct);
}
void USART1_Config(uint32_t Baudrate)
{
USART1_GPIO_Config();
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
USART_InitTypeDef USART_InitStruct;
USART_InitStruct.USART_BaudRate = Baudrate;
USART_InitStruct.USART_WordLength = USART_WordLength_8b;
USART_InitStruct.USART_StopBits = USART_StopBits_1;
USART_InitStruct.USART_Parity = USART_Parity_No;
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStruct.USART_Mode = USART_Mode_Tx;
USART_Init(USART1, &USART_InitStruct);
USART_Cmd(USART1, ENABLE);
}
配置串口1打印功能:
官方代码的打印底层有两个函数,我们只需要把发送函数进行完善即可,核心是添加一个USARTx_SnedByte(USART1,*buf++);
发送字节函数发送完一个字节地址进行偏移
发送一个自己函数如下:
void USARTx_SnedByte(USART_TypeDef *USARTx, char Byte)
{
while(USART_GetFlagStatus(USARTx,USART_FLAG_TC) == RESET);
USART_SendData(USARTx,Byte);
}
完整的Debug文件如下:
包括.c文件跟.h文件
总共打开了3个串口、根据需要选择对应的宏;这里选择的串口1进行打印测试
//完整的debug.c文件
#include "debug.h"
#include "stdio.h"
#include "usart.h"
__attribute__((used)) int _write(int fd, char *buf, int size)
{
int i;
for(i = 0; i < size; i++)
{
#if(DEBUG == DEBUG_UART1)
USARTx_SnedByte(USART1,*buf++);
#elif(DEBUG == DEBUG_UART2)
USARTx_SnedByte(USART2, *buf++);
#elif(DEBUG == DEBUG_UART3)
USARTx_SnedByte(USART3, *buf++);
#endif
}
return size;
}
/*********************************************************************
* @fn _sbrk
*
* @brief Change the spatial position of data segment.
*
* @return size: Data length
*/
__attribute__((used)) void *_sbrk(ptrdiff_t incr)
{
extern char _end[];
extern char _heap_end[];
static char *curbrk = _end;
if ((curbrk + incr < _end) || (curbrk + incr > _heap_end))
return NULL - 1;
curbrk += incr;
return curbrk - incr;
}
//完整的debug.h文件
#ifndef _DEBUG_H_
#define _DEBUG_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "ch32v30x.h"
#define DEBUG_UART1 1
#define DEBUG_UART2 2
#define DEBUG_UART3 3
#ifndef DEBUG
#define DEBUG DEBUG_UART1
#endif
#ifdef __cplusplus
}
#endif
#endif
打印测试结果:
至此基于于沁恒微电子工业级互联型RISC-V MCU CH32V307评估版串口打印调试信息就完成了,国产芯片是大势所趋,如果大家感兴趣可以点赞关注,下面有时间会更新其他外设的使用方法跟教程。
完整工程可以在后台私信找我领取。