一、启发

c语言嵌入式设计的本质无非就是“打开/关闭某个端口”或是“置高/置低某个引脚”。当我们想置高/置低某个引脚时,常常会使用如下两种方式。

/*置高PB6*/
GPIO_BOP(GPIOB) = GPIO_PIN_6;

/*置低PB6*/
GPIO_BC(GPIOB) = GPIO_PIN_6;

但这有个很大的问题,也就是并不直观!让我们来慢慢分析。

首先,我们为什么要置高置低某个引脚?因为我们在设计时是根据某个协议的,而协议一般都有默认的引脚名称。比如IIC的SCL、SDA,比如UART的RX、TX,比如CAN的CANH、CANL(这个会有点不同,但大致都是围绕CAN_HIGH、CAN_LOW展开)。但体现在硬件上,也就是PB6、PB7......。

IIC协议引脚连接示例(该图片为引用)

发现了吗?如果我们在设计时一直使用PB6这种硬件名称的话并不直观,哪怕是本人,在隔了一段时间后再看都得老老实实的去查手册,看看PB6对应的是什么功能的引脚。

既然如此,那有什么方法更加直观又强势吗?有的兄弟,有的!

那就是我下面将要讲的方法。

二、更加直观又强势的方法

请看最终结果:

void scl_50k_test()	//SCL以50k的频率振动。SDA以25k的频率振动。T = 10us*2
{
	delay_1us	(15)	;
	DataHigh	(SCL)	;
	delay_1us	(15)	;
	DataLow		(SCL)	;
	DataHigh	(SDA)	;
	delay_1us	(15)	;
	DataHigh	(SCL)	;
	delay_1us	(15)	;
	DataLow		(SCL)	;
	DataLow		(SDA)	;
}

如何?是不是很直观了呢?置高就写DataHigh( PIN_NAME ),置低就写DataLow( PIN_NAME )

我们来看看如何实现的。我们从结果慢慢倒推回去。

2.1 名称如何跟pin脚绑定(一)

首先是PIN_NAME,也就是SCL、SDA如何跟pin脚绑定的?

//xxx.h文件定义

typedef enum 
{
    SCL = 0,
	SDA = 1
} SCLSDA_enum;


//xxx.c文件定义


void test(SCLSDA_enum cdchoose)
{
	a( cdchoose )  //假设存在一种方法a()
}

test在声明时,声明的变量并不是常规的“int”、“char”等,而是我们在“xxx.h”中定义过的枚举类型定义。当我们使用test()时,把【test(SCL)】展开的情况如下:

并不是设计代码,而是按执行顺序展开!

SCLSDA_enum cdchoose = SCL;
test( cdchoose );
a( 0 )

很好,我们已经能看到一点雏形了,当我们输入SCL时,方法内部会自动转成0,SDA会自动转成1。让我们继续优化。

2.2 名称如何跟pin脚绑定(二)

我们现在要解决的就是,如何把 0/1 转换成 pin 脚。如下:

xxx.h文件定义

typedef enum 
{
    SCL = 0,
	SDA = 1
} SCLSDA_enum;

#define SCLpin GPIO_PIN_6
#define SCLclk GPIOB
#define SDApin GPIO_PIN_7
#define SDAclk GPIOB

#define CDCLKCHOOSEn 2U
#define CDPINCHOOSEn 2U



xxx.c文件定义

static uint32_t SCLSDA_CLK_CHOOSE[CDCLKCHOOSEn] = {SCLclk,SDAclk};
static uint32_t SCLSDA_PIN_CHOOSE[CDPINCHOOSEn] = {SCLpin,SDApin};

void DataHigh (SCLSDA_enum cdchoose)
{
	GPIO_BOP(SCLSDA_CLK_CHOOSE[cdchoose]) = SCLSDA_PIN_CHOOSE[cdchoose];
}

void DataLow (SCLSDA_enum cdchoose)
{
	GPIO_BC(SCLSDA_CLK_CHOOSE[cdchoose]) = SCLSDA_PIN_CHOOSE[cdchoose];
}

SCLSDA_CLK_CHOOSE[CDCLKCHOOSEn]是一个数组。输入0,就返回SCLclk,而SCLclk代表的是GPIOB,输入1同理。

SCLSDA_PIN_CHOOSE[CDPINCHOOSEn]也是一个数组。输入0,就返回SCLpin,而SCLpin代表的是GPIO_PIN_6,输入1同理。

需要注意的是“CDCLKCHOOSEn”与“CDPINCHOOSEn”是数组宽度。

所以,我们就可以达成我们的目标了!当我们使用方法DataHigh()时,展开后如下:

【DataHigh(SCL)】⬇️

DataHigh( 0 );

GPIO_BOP(SCLSDA_CLK_CHOOSE[ 0 ]) = SCLSDA_PIN_CHOOSE[ 0 ];

GPIO_BOP( GPIOB ) = GPIO_PIN_6;

Logo

openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。

更多推荐