🎬 秋野酱:《个人主页》
🔥 个人专栏:《Java专栏》《Python专栏》
⛺️心若有所向往,何惧道阻且长
文章目录
- 驱动封装
- 封装的一些疑问
- 数字走马灯实现
- 扩展知识
驱动封装
根据前面的内容可以将代码进行封装,封装后作为一个独立的整体出现:
#ifndef __NIXIE_H__
#define __NIXIE_H__
#include "config.h"
#define NIXIE_DI P44 // 数据输入
#define NIXIE_SCK P42 // 移位寄存器
#define NIXIE_RCK P43 // 锁存寄存器
#define NIXIE_PIN_INIT() { P4M0 &= ~0x1c; P4M1 &= ~0x1c; }
void NIXIE_init();
// u8 a_dat = 0x12; // 0001 0010 字母位
// u8 b_idx = 0x1F; // 0001 1111 数字位
void NIXIE_show(u8 a_dat, u8 b_idx);
// num对应数字在数组里的位置(索引)
// id 显示在指定位置(0 -> 7)
void NIXIE_display(u8 num, u8 id);
#endif
● 定义 NIXIE_init() 函数,负责对GPIO相关的初始化
● 定义 NIXIE_display()函数负责显示
#include "NIXIE.h"
#include "Delay.h"
#define GET_BIT_VAL(byte, pos) (byte & (1 << pos))
//#define NOP_TIME() NOP40() // 用于看logic分析仪
#define NOP_TIME() NOP2()
// 锁存操作 - 多行宏定义
#define RCK_ACTION() \
NIXIE_RCK = 0; \
NOP_TIME(); \
NIXIE_RCK = 1; \
NOP_TIME();
void NIXIE_init(){
NIXIE_PIN_INIT();
}
static void NIXIE_out(u8 dat){
char i;
// 8bit,先发出去的会作为高位
for(i = 7; i >= 0; i--){
NIXIE_DI = GET_BIT_VAL(dat, i);
// 寄存器的移位操作
NIXIE_SCK = 0;
NOP_TIME(); // 休眠一会儿
NIXIE_SCK = 1;
NOP_TIME(); // 休眠一会儿
}
}
// 每次可以显示多个,但是内容都是一样的a_dat
// u8 a_dat = 0x12; // 0001 0010 字母位
// u8 b_idx = 0x1F; // 0001 1111 数字位
void NIXIE_show(u8 a_dat, u8 b_idx){
// 显示 7.
// 0111 1000
// 先发字母位 (控制显示的内容) // 0点亮
// 8bit,先发出去的会作为高位
NIXIE_out(a_dat);
// 0,1,2,3....7
// 再发数字位 (控制显示哪几个) // 只要不是0,就是高电平
// 1111 1011
// 7.7.空7. 7.7.7.7. -------------------与二级制是反向
// 8bit,先发出去的会作为高位
NIXIE_out(b_idx);
// 锁存操作
RCK_ACTION();
}
以上为Nixie.h的实现,也是对之前代码的封装处理。
#include "Config.h"
#include "NIXIE.h"
#include "Delay.h"
int main() {
u8 a_dat = 0xF8; // 0001 0010 字母位
u8 b_idx = 0xFB; // 0001 1111 数字位
NIXIE_init();
// NIXIE_show写到循环外边即可
NIXIE_show(a_dat, b_idx);
while(1) {
}
}
封装的一些疑问
封装的特点
封装是面向对象程序设计中的一个重要概念,它将数据和行为封装在一起,形成一个独立的单元。下面是封装的特点:
- 数据隐藏:封装可以隐藏数据,只对外界公开必要的接口,从而保证数据的安全性和可靠性。
- 接口统一:封装可以将数据和行为组织在一起,形成一个类或对象,通过统一的接口对外提供服务,便于使用和管理。
- 信息隐藏:封装可以隐藏实现细节,只对外界公开必要的信息,从而降低了程序的复杂度和耦合度,提高了程序的可维护性和可扩展性。
- 可重用性:封装可以将数据和行为封装成一个独立的单元,便于复用和重复利用,提高了程序的开发效率和代码的可重用性。
- 封装和继承相结合:封装和继承是面向对象程序设计中的两个重要概念,它们相互配合,可以构建出更加复杂、灵活和可扩展的程序。
总之,封装是面向对象程序设计的核心思想之一,它可以提高程序的可靠性、安全性、可维护性和可扩展性,是程序设计中不可或缺的重要概念。
当前设计问题
接口设计:定义初始化(Nixie_init),和具体功能(Nixie_display),初始化和芯片开发板设计相关,功能的定义和业务相关。
初始化问题:为什么不用库函数?首先是可以使用库函数的。观察使用库函数和不是库函数的区别。一个初始化写在头文件,一个写在c文件。c文件是实现,做到抛开平台相关是最好的方案,也就是换了芯片平台,实现不动,通过改变头中的配置,就可以做到移植。(当然,理想状态是这样的,还得看实现复杂度。目标明确,尽量做到这个,为移植提供最少变化方案,这个是共识)
// 索引对应表格参见:
// https://www.yuque.com/icheima/stc8h/kmz2mllvxs1uvdfy#lLhhp
u8 code LED_TABLE[] =
{
// 0 1 2 -> 9 (索引012...9)
0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,
// 0. 1. 2. -> 9. (索引10,11,12....19)
0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,
// . - (索引20,21)
0x7F, 0xBF,
// AbCdEFHJLPqU (索引22,23,24....33)
0x88,0x83,0xC6,0xA1,0x86,0x8E,0x89,0xF1,0xC7,0x8C,0x98,0xC1
};
// 每次只显示一个
// \arg num 对应数字在数组里的位置(索引)
// \arg id 显示在指定位置(0 -> 7)
void NIXIE_display(u8 num, u8 id){
u8 a_dat = LED_TABLE[num]; // 0001 0010 字母位
u8 b_idx = 1 << id; // 0010 0000 数字位 5
NIXIE_show(a_dat, b_idx);
}
● index在没有封装前,一个bit表示一个灯。封装后表示灯的下标。这样设计符合人的思考习惯,函数就是让人调得舒服
● dat在没有封装前,是自己来总结灯的开灭,封装后表示自己定义的字符,通过下标访问。这样简化操作。还是为了调用舒服。
数字走马灯实现
#include "Config.h"
#include "NIXIE.h"
#include "Delay.h"
int main() {
u8 i;
// u8 a_dat = 0xF8; // 0001 0010 字母位
// u8 b_idx = 0xFB; // 0001 1111 数字位
NIXIE_init();
// NIXIE_show写到循环外边即可
// NIXIE_show(a_dat, b_idx);
while(1) {
// 1000 / (2 * 8) = 62.5帧/秒
// 走马灯
for(i = 0; i < 8; i++) {
NIXIE_display(i + 1, i);
delay_ms(100);
}
}
}
扩展知识
原理图中,大部分引脚我们已经知道了,但是还有些引脚功能不清楚。
● RESET: 10号引脚。
● OUTPUT_ENABLE: 13号引脚。