sbk100 发表于 2025-11-20 13:42:23

新手学STC单片机 实验四 138 译码器

实验内容


掌握红外发送的工作原理与遥控器的编码原理。
掌握红外发射的基本编程方法。


先上电路





74HC138 是一款高速 CMOS 器件,74HC138 引脚兼容低功耗肖特基 TTL(LSTTL)系列。
74HC138 译码器可接受 3 位二进制加权地址输入(A0, A1 和 A2),并当使能时,
提供 8 个互斥的低有效输出(Y0 至 Y7)。74HC138 特有 3 个使能输入端:两个低有
效(E1 和 E2)和一个高有效(E3)。除非 E1 和 E2 置低且 E3 置高,否则 74HC138
将保持所有输出为高。利用这种复合使能特性,仅需 4 片 74HC138 芯片和 1 个反相
器,即可轻松实现并行扩展,组合成为一个 1-32(5 线到 32 线)译码器。任选一
个低有效使能输入端作为数据输入,而把其余的使能输入端作为选通端,则 74HC138
亦可充当一个 8 输出多路分配器,未使用的使能输入端必须保持绑定在各自合适的
高有效或低有效状态。


真值表





本实验程序为用 138 译码器实现实验一中的流水灯效果,与实验一相比,使用
138 可以节省 I/O 口的开销,此外 138 也可以用作数码管位选。



实验测试
连线:P0.0- P0.2 接 JP51, JP15 接 JP78.
实验现象:在流水灯上可以看到跑马灯效果(即逐个点亮)。


代码分析

/*******************************************************
* 程序功能:138
*******************************************************/
#include "hal.h"
#ifndef FOSC //晶振
#define FOSC 12000000L
#endif
#define DATA P0
//#define HIGH (65536-5000)/256 //ms
//#define LOW (65536-5000)%256
uchar num;

/*******************************************************
//函数名称:Timer0Init()
//函数功能:定时器0初始化函数 10毫秒@12MHz
//入口参数:无
//返回参数:无
********************************************************/
void Timer0Init(void)
{
    TIMER_CLK_DIV(0,12); //定时器时钟12T模式
    TIMER_TIME(0);       //设置定时器0定时模式
    TIMER_MODE(0,0);   //设置定时器0模式0
    TL0 = LOW;         //设置定时初值
    TH0 = HIGH;          //设置定时初值
    CLR_TIMER_FLAG(0);   //清除TF0标志
}

/*******************************************************
//函数名称:main()
//函数功能:程序主函数
********************************************************/
void main()
{
    num=0xfe;
    Timer0Init();      //初试化定时器
    TIMER_RUN(0,START);//定时器0开始计时
    TIMER_INT_EN(0,ON);//开启定时器0中断
    INT_GLOBAL_ENABLE(ON);//开启全局中断
    while(1)
    {
    }
}

/*******************************************************
//函数名称:Timer0_ISR()
//函数功能:定时器0中断服务程序
//入口参数:无
//返回参数:无
********************************************************/
void Timer0_ISR() interrupt 1 using 1
{
    static unsigned char i;
    if( ++i>=50)
    {
      i=0;
      DATA=num;
      if(num==0x07) //检测是否移到最左端?
      {
            num=0x00;
      }
      else
      {
            num++;
      }
    }
}

// 程序相关宏文件:
#define INT_GLOBAL_ENABLE(on) EA=(!!on) //开
全局中断

/********************************************************
// 功能:定时器运行操作控制
// 参数:num 计数器号(0-4) ;on 运行控制,1:启动,0停止
*********************************************************/
#define TIMER_RUN(num,on) \
    st( \
      if(num==0) \
            TR0=on; \
      else if(num==1) \
            TR1=on; \
      else if(num==2) \
            (on)?(AUXR |=BIT4):(AUXR &= ~BIT4); \
      else if(num==3) \
            (on)? (T4T3M |= BIT3):(T4T3M &=~BIT3);\
      else if(num==4) \
            (on)? (T4T3M|= BIT4):(T4T3M &=~BIT4);\
    )

/********************************************************
// 功能:定时器定时操作控制
// 参数:num 计数器号(0-4)
*********************************************************/
#define TIMER_TIME(num)\
    st( \
      if(num==0) \
            TMOD |=~BIT2; \
      else if(num==1) \
            TMOD |=~BIT6; \
      else if(num==2) \
            AUXR |=~BIT3; \
      else if(num==3) \
            T4T3M |= ~BIT2; \
      else if(num==4) \
            T4T3M |= ~BIT6;\
    )

/********************************************************
// 功能:定时器中断使能操作控制
// 参数:num 计数器号(0-4) ;on 使能控制,1:允许,0禁止 //1溢出
中断允许
*********************************************************/
#define TIMER_INT_EN(num,on) \
    if(num==0) \
      ET0=on; \
    else if(num==1) \
      ET1=on; \
    else if(num==2) \
      (on) ? (IE2 |= BIT3) : (IE2 &= ~BIT3); \
    else if(num==3) \
      (on) ? (IE2 |= BIT5) : (IE2 &= ~BIT5); \
    else if(num==4) \
      (on) ? (IE2 |= BIT6) : (IE2&= ~BIT6);

/********************************************************
// 功能:定时器工作模式选择
// 参数:num 计数器号(0-1) ;sel模式选择(0-3)
// 0:16位重载 1:16位计数器 2:8位重载 3:计数器无效
*********************************************************/
#define TIMER_MODE(num,sel) \
    if(sel<4) \
    { \
      if(num==0) \
      { \
            TMOD &= ~0x03; \
            TMOD |=sel; \
      } \
      else if(num==1) \
      { \
            TMOD &= ~0x30; \
            TMOD |=sel<<3; \
      } \
    }

/********************************************************
// 功能:定时器定时时间分频选择
// 参数:num 计数器号(0-4); sel分频选择; 1:1分频,0-12分频
*********************************************************/
#define TIMER_CLK_DIV(num,sel) \
    st( \
      if(num==0) \
            (sel==1) ? (AUXR |= BIT7) :(AUXR &= ~BIT7); \
      else if(num==1) \
            (sel==1) ? (AUXR |= BIT6) :(AUXR &= ~BIT6); \
      else if(num==2) \
            (sel==1) ? (AUXR |= BIT2) :(AUXR &= ~BIT2); \
      else if(num==3) \
            (sel==1) ? (T4T3M |= BIT1) :(T4T3M &= ~BIT1); \
      else if(num==4) \
            (sel==1) ? (T4T3M |= BIT5) :(T4T3M &= ~BIT5);\
    )

/*************************************
// 功能:清除定时器中断标志 //清除溢出
中断
// 参数:num 计数器号(0-1)
*********************************************************/
#define CLR_TIMER_FLAG(num) \
    st( \
      if(num==0) \
            TF0=0; \
      else if(num==1) \
            TF0=0; \
    )


页: [1]
查看完整版本: 新手学STC单片机 实验四 138 译码器