目录
一、相关知识
1.串行存储器映射扩展技术
2.注意
二、所要实现的功能
三、代码实现
1.参数定义
2.138译码器通道选择函数
3.初始化系统
4.延时函数
5.IO模式下LED灯与数码管的控制
6.MM模式下LED灯与数码管的控制
7.完整代码
四、运行图片
关于LED灯、共阳数码管都在之前的文章介绍过了,此处不再介绍了。
一、相关知识
1.串行存储器映射扩展技术
不需要在意太多,基本上只需要掌握外部资源的地址映射关系:0x8000-LED灯、0xa000-蜂鸣器和继电器、0xc000-数码管位选、0xe000-数码管段码。
可以发现,0x80、0xa0、0xc0、0xe0部分和通道选择函数中的P2最后面“与”上的数一样,可以由此来记忆。
// 通道选择函数
void HC138_Init( unsigned char channel )
{
switch( channel )
{
case 0:
P2 = ( P2 & 0x1f ) | 0x00; // 0
break;
case 4:
P2 = ( P2 & 0x1f ) | 0x80; // Y4C
break;
case 5:
P2 = ( P2 & 0x1f ) | 0xa0; // Y5C
break;
case 6:
P2 = ( P2 & 0x1f ) | 0xc0; // Y6C
break;
case 7:
P2 = ( P2 & 0x1f ) | 0xe0; // Y7C
break;
}
}
2.注意
①在使用串行存储器映射扩展技术时,需要在代码文件中引入“absacc.h”文件,通过“XBYTE”关键字来直接操作扩展资源;
②如果要用到4×4的矩阵键盘,那么尽量不要使用存储器映射技术,因为存储器映射会占用P4.2引脚,这时就需要用常使用的IO扩展的方式了。如下图所示:
③IO扩展技术和存储器映射扩展技术的切换是通过板子上的J13引脚的跳帽来实现的。当跳帽位于2、3脚时是IO模式,当跳帽位于1、2脚时是MM模式。原理图与板子上的位置上下颠倒。如图所示:
二、所要实现的功能
分别在IO模式和MM模式下完成。首先点亮指示灯低四位,关闭高四位,延时一段时间,点亮指示灯的高四位,关闭低四位,再延时一段时间,关闭所有指示灯。然后依次逐个点亮数码管,从左往右,依次显示0~7。循环实现上述功能。
三、代码实现
1.参数定义
#include <STC15F2K60S2.H>
#include "absacc.h"
#include "Delay_ms.h"
// 不加“code”会影响单片机的运行速度,会改变RAM,加了code之后内容就固定不变了,不会多占用RAM空间
// 共阳数码管段码
unsigned char code SMG_Duanma[18] =
{
0xc0 , 0xf9 , 0xa4 , 0xb0 , 0x99 ,0x92 , 0x82 , 0xf8 , 0x80 ,
0x90 , 0x88 , 0x80 , 0xc6 , 0xc0 ,0x86 , 0x8e , 0xbf , 0x7f
}; // 0~F - .
2.138译码器通道选择函数
// 通道选择函数
void HC138_Init( unsigned char channel )
{
switch( channel )
{
case 0:
P2 = ( P2 & 0x1f ) | 0x00; // 0
break;
case 4:
P2 = ( P2 & 0x1f ) | 0x80; // Y4C
break;
case 5:
P2 = ( P2 & 0x1f ) | 0xa0; // Y5C
break;
case 6:
P2 = ( P2 & 0x1f ) | 0xc0; // Y6C
break;
case 7:
P2 = ( P2 & 0x1f ) | 0xe0; // Y7C
break;
}
}
3.初始化系统
// 初始化系统
void System_Init(void)
{
// 关闭LED灯
HC138_Init( 4 );
P0 = 0xff;
// 关闭蜂鸣器和继电器
HC138_Init( 5 );
P0 = 0xaf; // 1010 1111
// 关闭通道选择
HC138_Init( 0 );
}
4.延时函数
void Delay_tms( unsigned int t )
{
int i;
while( t-- )
{
for( i=115 ; i>0 ; i-- )
{}
}
}
5.IO模式下LED灯与数码管的控制
// LED灯亮
void LED_Light_IO(void)
{
HC138_Init( 4 );
P0 = 0xf0; // 低四位亮
Delay_tms( 1000 );
P0 = 0x0f; // 高四位亮
Delay_tms( 1000 );
P0 = 0xff; // 全灭
Delay_tms( 1000 );
HC138_Init( 0 );
}
// 数码管亮
void SMG_Light_IO(void)
{
unsigned char i = 0;
for( i=0 ; i<8 ; i++ )
{
HC138_Init( 6 );
P0 = 0x01 << i;
HC138_Init( 7 );
P0 = SMG_Duanma[ i ];
Delay_tms( 1000 );
}
P0 = 0xff; // 数码管消抖
HC138_Init( 0 );
}
6.MM模式下LED灯与数码管的控制
// LED灯亮
void LED_Light_MM(void)
{
XBYTE[ 0x8000 ] = 0xf0;
Delay_tms( 1000 );
XBYTE[ 0x8000 ] = 0x0f;
Delay_tms( 1000 );
XBYTE[ 0x8000 ] = 0xff;
Delay_tms( 1000 );
}
// 数码管亮
void SMG_Light_MM(void)
{
unsigned char i = 0;
for( i=0 ; i<8 ; i++ )
{
XBYTE[ 0xc000 ] = 0x01 << i;
XBYTE[ 0xe000 ] = SMG_Duanma[ i ];
Delay_tms( 1000 );
}
XBYTE[ 0xe000 ] = 0xff;
}
7.完整代码
#include <STC15F2K60S2.H>
#include "absacc.h"
#include "Delay_ms.h"
// 不加“code”会影响单片机的运行速度,会改变RAM,加了code之后内容就固定不变了,不会多占用RAM空间
// 共阳数码管段码
unsigned char code SMG_Duanma[18] =
{
0xc0 , 0xf9 , 0xa4 , 0xb0 , 0x99 ,0x92 , 0x82 , 0xf8 , 0x80 ,
0x90 , 0x88 , 0x80 , 0xc6 , 0xc0 ,0x86 , 0x8e , 0xbf , 0x7f
}; // 0~F - .
// 通道选择函数
void HC138_Init( unsigned char channel )
{
switch( channel )
{
case 0:
P2 = ( P2 & 0x1f ) | 0x00; // 0
break;
case 4:
P2 = ( P2 & 0x1f ) | 0x80; // Y4C
break;
case 5:
P2 = ( P2 & 0x1f ) | 0xa0; // Y5C
break;
case 6:
P2 = ( P2 & 0x1f ) | 0xc0; // Y6C
break;
case 7:
P2 = ( P2 & 0x1f ) | 0xe0; // Y7C
break;
}
}
// 初始化系统
void System_Init(void)
{
// 关闭LED灯
HC138_Init( 4 );
P0 = 0xff;
// 关闭蜂鸣器和继电器
HC138_Init( 5 );
P0 = 0xaf; // 1010 1111
// 关闭通道选择
HC138_Init( 0 );
}
// ************************IO扩展************************( J13接到IO模式 )
// LED灯亮
void LED_Light_IO(void)
{
HC138_Init( 4 );
P0 = 0xf0; // 低四位亮
Delay_tms( 1000 );
P0 = 0x0f; // 高四位亮
Delay_tms( 1000 );
P0 = 0xff; // 全灭
Delay_tms( 1000 );
HC138_Init( 0 );
}
// 数码管亮
void SMG_Light_IO(void)
{
unsigned char i = 0;
for( i=0 ; i<8 ; i++ )
{
HC138_Init( 6 );
P0 = 0x01 << i;
HC138_Init( 7 );
P0 = SMG_Duanma[ i ];
Delay_tms( 1000 );
}
P0 = 0xff; // 数码管消抖
HC138_Init( 0 );
}
// ************************IO扩展************************
// ************************存储器扩展************************( J13接到MM模式 )
// LED灯亮
void LED_Light_MM(void)
{
XBYTE[ 0x8000 ] = 0xf0;
Delay_tms( 1000 );
XBYTE[ 0x8000 ] = 0x0f;
Delay_tms( 1000 );
XBYTE[ 0x8000 ] = 0xff;
Delay_tms( 1000 );
}
// 数码管亮
void SMG_Light_MM(void)
{
unsigned char i = 0;
for( i=0 ; i<8 ; i++ )
{
XBYTE[ 0xc000 ] = 0x01 << i;
XBYTE[ 0xe000 ] = SMG_Duanma[ i ];
Delay_tms( 1000 );
}
XBYTE[ 0xe000 ] = 0xff;
}
// ************************存储器扩展************************
int main(void)
{
System_Init();
while(1)
{
// IO模式打开
LED_Light_IO();
SMG_Light_IO();
// MM模式打开
//LED_Light_MM();
//SMG_Light_MM();
}
}