找回密码
 立即注册
查看: 55|回复: 0

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

[复制链接]
  • 打卡等级:偶尔看看III
  • 打卡总天数:31
  • 最近打卡:2025-12-17 09:44:38

20

主题

29

回帖

85

积分

注册会员

积分
85
发表于 2025-11-20 13:42:23 | 显示全部楼层 |阅读模式
实验内容


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


先上电路

截图202511201327099872.jpg



  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 输出多路分配器,未使用的使能输入端必须保持绑定在各自合适的
高有效或低有效状态。


真值表

截图202511201328174844.jpg



本实验程序为用 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; \
    )


回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-12-17 17:27 , Processed in 0.102518 second(s), 45 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表