本帖最后由 wanyhong 于 2021-10-10 23:59 编辑
#申请原创#@21小跑堂
@21小跑堂
@21小跑堂
@21小跑堂
最近要使用沁恒CH573F做一个项目,项目中使用的GPIO较多,只能对外有一路串口使用,而且需要接其他设备,所以开发过程中调试就是个**烦。
因为只是调试使用,所以只需要一个发送就可以,在本项目中我使用了一个普通的GPIO模拟串口发送,进行调试信息输出。
我们经常使用串口通讯,通常都是使用1位起始位,8位数据位,1位停止位,没有校验位 的形式传输。
以下两点是要特别注意的地方:
1、串口异步传输在空闲状态时都必须是高电平。第一位传输的是起始位,起始位会将原来空闲时的高电平拉成低电平,起始位用来来标识数据开始传输,提示接收方准备开始接收数据;
2、当接收方第一次检测到一个下降沿时,就表示接收到了起始位。起始位后就是8位的数据位,接收方在接收每一位数据的时候会采集几十次,如果结果都是低电平,则接收到的数据位0,如果结果都是高电平,则棘手到的数据位是1。1位停止位会将电平拉成高电平,以为接收下一个数据做准备。
结合以上协议就可以开始写代码了,下面我就直接贴代码:
#include<stdio.h>
#include<stdarg.h>
#define DATA_HIGH() GPIOB_SetBits(DEBUG_VCOM_PIN) //高电平 DEBUG_VCOM_PIN PB14
#define DATA_LOW() GPIOB_ResetBits(DEBUG_VCOM_PIN) //低电平
/* 主时钟频率 36M
* 延时 (微秒) 波特率
800 1200
400 2400
200 4800
100 9600
50 19200
*/
#define BAUD_DELAYUS 50
void SendByte(UINT8 val)
{
UINT8 i = 0;
DATA_LOW(); //起始位
DelayUs(BAUD_DELAYUS);
for(i = 0; i < 8; i++) //8位数据位
{
if(val & 0x01)
DATA_HIGH();
else
DATA_LOW();
DelayUs(BAUD_DELAYUS);
val >>= 1;
}
DATA_HIGH(); //停止位
DelayUs(BAUD_DELAYUS);
}
void PrintString(UINT8 *str)
{
while(*str != 0)
{
SendByte(*str);
str++;
}
}
/******************************************************************************************
*** 函数名称: Log
*** 输入参数: 无
*** 返 回 值: 无
*** 说 明:自定义串口 printf功能
*** 功能说明:
*** 编者 时间 版本
******************************************************************************************/
void Log(char *format, ...)
{
uint8_t str[256];
va_list ap;
va_start(ap, format); //初始化 ap 变量
vsnprintf((char *)str, sizeof(str), format, ap); //可变参数。用于向字符串中打印数据、数据格式用户自定义
va_end(ap); //允许使用了 va_start 宏的带有可变参数的函数返回
PrintString(str);
}
其中LOG函数就是常用的格式化输出,官方库将printf已经定义,这里自定义了格式化输出函数,以便区别于官方库,防止冲突,这里再贴几个宏定义,调试时使用起来更方便
#ifdef DEBUG
#define LOG(...) Log("\r\n%s(%d): %s", __FILE__, __LINE__, __VA_ARGS__)
#define LOG_FMT(fmt,...) \
{ \
Log("\r\n%s(%d): ", __FILE__, __LINE__); \
Log(fmt,__VA_ARGS__); \
}
#else
#define LOG(...)
#define LOG_FMT(fmt,...)
#endif
工程配置中宏定义对DEBUG建议做如下设置:
最后我们来看下运行效果,波特率延时我使用的是50微秒,所以波特率设置为19200.
|