点师大灯——STM32应用笔记(六)

六、我要的是开关

        上面的分析和代码,看似有理有据,实则乱七八糟。一团乱麻算不上,顶多一个P。

        文字上把U1 MCU假设成开关,代码上没体现。这种想法,符合我们的天然思路,是面向对象的思维。从这句开始,我们走上OOP,构建我们的葫芦世界,使用C++的语言了。

        我们想要的是个开关,就创造一个开关,开关听招呼就行。具体开关怎么实现,由开关自己解决。

        今天的开关实现很简单,当然有很多方法。选天然思维来,OOP方法。构建每一个对象,然后按照依赖关系合并。

                算上开关,一个四个对象。我们分析和合并一下,一个开关,各对应一个ODR、CR和APB2ENR。这里我不考虑怎么变化,所以另外三个对象,可以成为开关的属性成员。合并后的开关对象,成了这样

                终于有了点自己的葫芦长出来的感觉,下面上代码。

//为了简洁,不包含任何头文件
//体现面向对象的版本
//用 C++ 语言和参考手册的寄存器编写程序
//修电视的老五 2024-9-12

/***********************************************************************************/
#define uint32_t unsigned int
#define uint16_t unsigned short
//代表图1中“我们”的类
class We;
//代表图1中“开关”的类
class KnifeSwitch;
int main();
/***********************************************************************************/
class We{
	public:
		//图1, 需要是呼唤开关
		void Need(KnifeSwitch& knife_switch);
};
class KnifeSwitch{
	public:
		//开关只接受开和关两种呼唤
		enum call_enum{ OPEN, CLOSE };
		//图1中的呼唤
		void Call( enum call_enum need );
		KnifeSwitch();
	private:
		//图2中的ODR,CR,APB2ENR,合并后成为
		//图3中的三个地址
		volatile uint32_t *odr_addr;
		volatile uint32_t *cr_addr;
		volatile uint32_t *apb2enr_addr;
};
/***********************************************************************************/
void We::Need(KnifeSwitch& knife_switch)
{
	//需要就是开关
	knife_switch.Call(KnifeSwitch::OPEN);
	knife_switch.Call(KnifeSwitch::CLOSE);
}
/***********************************************************************************/
KnifeSwitch::KnifeSwitch()
{
	//初始化三个地址表示的对象
	odr_addr 		 = (uint32_t*) (0x40000000 + 0x10000 + 0x0800 + 0x0c);
	cr_addr  		 = (uint32_t*) (0x40000000 + 0x10000 + 0x0800 + 0x00);
	apb2enr_addr = (uint32_t*) (0x40000000 + 0x20000 + 0x1000 + 0x18);
	
	//APB2ENR对象,开启GPIOA的时钟
	const uint32_t gpioa_clk_enable = 0x04;
	*apb2enr_addr |= gpioa_clk_enable;
	//CR对象,配置PIN 0 为输出开漏模式
	const uint32_t gpio_pin_0_config = 0x02;
	uint32_t temp;
	temp = *cr_addr, temp &= 0xfffffff0, temp |= gpio_pin_0_config, *cr_addr = temp;
}
void KnifeSwitch::Call( enum call_enum need )
{
	//我们的电路是高电平关闭,低电平开启
	const uint16_t gpio_pin_off = 0x0001;
	if( need == CLOSE )
		//ODR对象的操作
		*odr_addr &= ~gpio_pin_off;
	else
		//ODR对象的操作
		*odr_addr |= gpio_pin_off;
}

int main()
{
	//图1,我们和开关都有了
	KnifeSwitch knife_switch;
	We					we;
	while(1)
	{
		//图1,需要呼唤开关
		we.Need(knife_switch);
	}
	return 0;
}

        和上篇的代码比较,有整齐了的感觉,小葫芦长了出来。

        这个葫芦种出来,有很多的叶子,需要修剪。很无奈的,我们从小就见多了这种化简,以数学最多。加减乘除的混合运算式,计算一元二次方程,计算方程组,计算三角函数,求值,求长度,求体积。。。。。。求心理阴影面积。

        总算被孙子打了,现在世界真不像样!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值