基于数组法的IAP15F261S2型单片机外设控制方法研究
2024-07-14黄庆武胡婷
黄庆武 胡婷
摘 要:单片机I/O口控制,一般采用地址分时复用技术,LED灯、蜂鸣器、继电器、数码管等是基于单片机外设控制的电子系统的常见外设,采用数组法,根据I/O口的特征,对应建立一维数组或二维数组,分别对控制外设的地址和参数进行赋值,较过去常用的逐位选择取值法,编程代码结构优化,实现相同控制功能指令,执行指令速度更快,代码可复用性强,实现功能思路简单明了。
关键词:数组法;锁存器;赋值;LED;继电器;数码管
中图分类号:TP202 文献标志码:A 文章编号:1671-0797(2024)13-0006-04
DOI:10.19514/j.cnki.cn32-1628/tm.2024.13.002
0 引言
单片机体积小、质量轻,广泛应用于智能仪表、实时工控、通信设备、导航系统、家用电器等领域。从20世纪90年代开始,单片机技术逐渐发展成熟,无论是自动测量还是智能仪表的实践,都能看到单片机技术的身影[1]。当前工业发展进程中,电子行业属于新兴产业,人们将电子信息技术与单片机技术相融合,有效提高了单片机应用效果。
IAP15F261S2型单片机是STC生产的单时钟/机器周期(1T)的单片机,采用STC第八代加密技术,是集高速、高可靠、低功耗、超强抗干扰等功能于一体的新一代8051单片机,指令代码完全兼容传统8051、ISP/IAP系列型号,在系统/应用可编程,无须编程器,无须仿真器,内部集成R/C时钟,ISP编程时5~35 MHz宽范围可设置,可彻底省去外部昂贵的晶振和外部复位电路,LQFP44是44引脚的常用封装形式。
1 常用IAP15F261S2型单片机外设控制电路组成及原理
以典型IAP15F261S2型单片机外设控制如国信长天V20CT107S控制板为例,介绍外设器件控制原理,该控制板主要用于全国大学生蓝桥杯电子设计竞赛,具有较好的单片机外设控制的通用性,控制板主要外设包含有74HC138译码器、74HC02或非门电路芯片、M74HC573MIR锁存器、ULN2003耐高压大电流驱动芯片、LED灯、继电器、蜂鸣器、DS17SEG-4数码管、1 kΩ大小阻值电阻。单片机的P0端口,通过程序控制外设LED灯、继电器、蜂鸣器、数码管的通断,为能实现4种外设的同步控制,采用了以P2端口P25、P26、P27引脚为地址的分时复用技术,74HC138译码器的A、B、C分别与之相连接,通过程序控制P25、P26、P27引脚地址变化,实现74HC138译码器Y0-Y7通路的低电平输出,该部分电路原理图如图1所示。Y4、Y5、Y6、Y7引脚与或非门芯片74HC02的U24、U25、U26、U27连接,或非门芯片的输出状态由P2端口P25、P26、P27引脚状态确定,或非门输出状态为高电平时,使能锁存器M74HC573MIR,通过对P0端口的状态的锁存,达到分时复用的功能,该部分电路原理图如图2所示[2]。通过锁存器的Q1至Q8输出端,实现LED灯、继电器、蜂鸣器、数码管等外设的控制。
2 传统单片机外设控制思路及程序实现方法
传统单片机P0端口分时复用思路是根据控制目的需要,将P0端口赋值,使用选择结构程序,将P2端口赋值,使对应的74HC138译码器通路导通,74HC138译码器输出信号与74HC02或非门电路逻辑计算,计算结果使能M74HC573MIR锁存器,随后将P2端口赋零值,P0端口状态得以保存。以数码管第一位显示为例,对端口定义部分代码,参考如下[3]:
void shumaguanshow(unsigned char position,unsigned char value)
{
switch(position)
{
case 1: P0=0x01;P2=(P2&0x1f)|0xc0;P2=
P2&0x1f;
{
if(value==0) {P0=0xc0;P2=(P2&0x1f)|0xe0;P2=P2=P2&0x1f;break;}
if(value==1) {P0=0xf9;P2=(P2&0x1f)|0xe0;P2=P2=P2&0x1f;break;}
if(value==2) {P0=0xa4;P2=(P2&0x1f)|0xe0;P2=P2=P2&0x1f;break;}
if(value==3) {P0=0xb0;P2=(P2&0x1f)|0xe0;P2=P2=P2&0x1f;break;}
if(value==4) {P0=0x99;P2=(P2&0x1f)|0xe0;P2=P2=P2&0x1f;break;}
if(value==5) {P0=0x92;P2=(P2&0x1f)|0xe0;P2=P2=P2&0x1f;break;}
if(value==6) {P0=0x82;P2=(P2&0x1f)|0xe0;P2=P2=P2&0x1f;break;}
if(value==7) {P0=0xF8;P2=(P2&0x1f)|0xe0;P2=P2=P2&0x1f;break;}
if(value==8) {P0=0x80;P2=(P2&0x1f)|0xe0;P2=P2=P2&0x1f;break;}
if(value==9) {P0=0x90;P2=(P2&0x1f)|0xe0;P2=P2=P2&0x1f;break;}
}
}
}
上述代码仅对第1位数码管的0~9的10个状态值进行显示,如要求显示更多状态值,则可按此规则编程,2至8位的数码管的状态显示,通过复制上述代码中的状态值即可。此方法思路清晰,通过数码管的1至8位的位置选择,随后对数码管赋值,即可实现数码管的按位显示功能,如要实现连续显示,可利用人眼的视觉差,使用延时函数或定时器进行控制。如编写一个数码管完整显示函数代码,代码长度将超过200行,该方法存在代码结构复杂、执行时间长、重复率高等不足。关于LED通路及继电器、蜂鸣器通路分析类似,此代码编写思路方法给编程者造成了困难。
有关LED灯通路控制的程序代码,过去常用的编写方式如下:
void ledshow(unsigned char position,unsigned char value)
{
switch(position)
{
case 1:
if(value==1){P0=0xfe;P2=(P2&0x1f)|0x80;P2=P2&0x1f;break;}
if(value==0){P0=0xff;P2=(P2&0x1f)|0x80;P2=P2&0x1f;break;}
case 2:
if(value==1){P0=0xfd;P2=(P2&0x1f)|0x80;P2=P2&0x1f;break;}
if(value==0){P0=0xff;P2=(P2&0x1f)|0x80;P2=P2&0x1f;break;}
case 3:
if(value==1){P0=0xfb;P2=(P2&0x1f)|0x80;P2=P2&0x1f;break;}
if(value==0){P0=0xff;P2=(P2&0x1f)|0x80;P2=P2&0x1f;break;}
case 4:
if(value==1){P0=0xf7;P2=(P2&0x1f)|0x80;P2=P2&0x1f;break;}
if(value==0){P0=0xff;P2=(P2&0x1f)|0x80;P2=P2&0x1f;break;}
case 5:
if(value==1){P0=0xef;P2=(P2&0x1f)|0x80;P2=P2&0x1f;break;}
if(value==0){P0=0xff;P2=(P2&0x1f)|0x80;P2=P2&0x1f;break;}
case 6:
if(value==1){P0=0xdf;P2=(P2&0x1f)|0x80;P2=P2&0x1f;break;}
if(value==0){P0=0xff;P2=(P2&0x1f)|0x80;P2=P2&0x1f;break;}
case 7:
if(value==1){P0=0xbf;P2=(P2&0x1f)|0x80;P2=P2&0x1f;break;}
if(value==0){P0=0xff;P2=(P2&0x1f)|0x80;P2=P2&0x1f;break;}
case 8:
if(value==1){P0=0x7f;P2=(P2&0x1f)|0x80;P2=P2&0x1f;break;}
if(value==0){P0=0xff;P2=(P2&0x1f)|0x80;P2=P2&0x1f;break;}
}
}
同样,该方法代码结构复杂,重复率高,有改进及优化的空间,依据此方法,编写相关P0端口的继电器及蜂鸣器通路分时复用控制代码,在此不再描述。
3 数组法控制单片机外设的思路方法及实现
为解决上述代码问题,若采用数组法,分别将数码管的位置选择值和显示状态值定义为数组变量值,通过赋值语句直接对数组取值,可有效减少代码量重复率,同时不再使用选择结构语句,代码复杂程度降低,整体结构简单易懂。以数码管为例,使用数组法的参考代码如下:
unsigned char smg_position[]={0,1,2,4,8,16,32,64,
128};
unsigned char smg_value[]={0xc0,0xf9,0xa4,0xb0,
0x99,0x92,0x82,0xf8,0x80,0x90,0xbf};
void smg(unsigned int position,unsigned int value)
{
P0=smg_position[position];P2=(P2&0x1f)|0xc0;P2=P2&0x1f;
P0=smg_value[value];P2=(P2&0x1f)|0xe0;P2=P2&0x1f;
}
在上述代码中,数组变量smg_position[]定义为数码管位置选择值,由于在数组定义中,数组变量地址从0开始,而数码管位置值为1至8,为此在数组变量smg_position[]中,将smg_position[0]定义为0,数组变量smg_value[]中,首地址值为1,故保持不变。上述7行代码即可实现原思路方法200行以上代码的显示功能[4]。
关于LED通路的数组法编程代码,由于LED灯的状态显示,则需定义一个二维数组,二维数组的行值为LED灯的位置选择位,二维数组的列值为LED灯的状态显示。数组地址定义为以0为首地址,故关状态值(即0)在前,开状态值(即1)在后,同样在二维数组的第0行补一行{0,0}代码,LED灯的显示,使用数组法的参考代码如下[5]:
unsigned char LED_position_value[][2]= {{0,0},{0xff,0xfe},{0xff,0xfd},{0xff,0xfb},{0xff,0xf7},{0xff,0xef},{0xff,0xdf},{0xff,0xbf},{0xff,0x7f}};
void ledshow(unsigned char position,unsigned char value)
{
P0=LED_position_value[position][value];P2=(P2&0x1f)|0x80;P2=P2&0x1f;
}
关于继电器与蜂鸣器通路的数组法编程代码,对于部分未使用P0端口值,又占有数组中的位置,不得将其删除,而应以代码{0,0}代替,同理第0行补一行{0,0}代码,继电器及蜂鸣器电路功能实现,使用数组法编程的参考代码如下:
unsigned char JDFM_position_value[][2]=
{{0,0},{0,0},{0,0},{0,0},{0,0},{0,0x10},{0,0},{0,0x40},{0,0}};
void JDFMshow(unsigned char position,unsigned char value)
{
P0=JDFM_position_value[position][value];P2=(P2&0x1f)|0xa0;P2=P2&0x1f;
}
4 实验效果验证
利用keil5软件,完善主函数功能代码,并生成.hex文件,使用STC_ISP代码下载软件,对控制板进行程序烧写。以数码管显示20240328、LED灯第1和第8盏灯点亮为例,主函数的代码参考如下[6]:
void main()
{
while(1)
{
smg(1,2);Delay1000us();
smg(2,0);Delay1000us();
smg(3,2);Delay1000us();
smg(4,4);Delay1000us();
smg(5,0);Delay1000us();
smg(6,3);Delay1000us();
smg(7,2);Delay1000us();
smg(8,8);Delay1000us();
Ledshow(1,1);Delay1000us();
Ledshow(8,1);Delay1000us();
}
}
数码管及LED灯的显示效果如图3所示,而继电器和蜂鸣器(发声)无视觉效果,在此不作显示。
5 结论
本文通过数组法,实现了IAP15F261S2型单片机P0端口的分时复用功能,代码编写思路清晰,结构简单,具有较好的实用性,为单片机端口的外设控制提供了一种新的方法。
[参考文献]
[1] 宏晶STC官网.STC15系列单片机用户手册[Z],2023.
[2] 阎石.数字电子技术基础[M].6版.北京:高等教育出版社,2016.
[3] 王英明,张露露,蒋林,等.C语言程序设计[M].5版.北京:清华大学出版社,2022.
[4] 林立,张俊亮.单片机原理及应用[M].2版.北京:电子工业出版社,2024.
[5] 徐广振,刘小莉.单片机技术应用项目化教程(C语言版)[M].2版.北京:电子工业出版社,2021.
[6] 皮大能,胡学芝.单片机控制系统抗干扰技术[J].机械制造与自动化,2005(2):117-119.
作者简介:黄庆武(1981—),男,湖北黄石人,硕士研究生,助理讲师,研究方向:电气与电子技术。
胡婷(1996—),女,湖北武汉人,硕士研究生,助理讲师,研究方向:计算机与人工智能技术。