欢迎光临散文网 会员登陆 & 注册

第10章-实例练习与经验积累(上:跟堂作业)

2023-08-31 22:08 作者:feifeiluan2  | 我要投稿

这节课,真没意思,不想做,拖了好几天,快没感觉了

//跟堂作业:秒表

#include <reg52.h>

typedef signed char i8;
typedef unsigned char u8;
typedef signed int i16;
typedef unsigned int u16;
typedef signed long i32;
typedef unsigned long u32;

sbit ADDR3 = P1 ^ 3;
sbit ENLED = P1 ^ 4;

sbit KEY1 = P2 ^ 4;
sbit KEY2 = P2 ^ 5;
sbit KEY3 = P2 ^ 6;
sbit KEY4 = P2 ^ 7;

u8 code LedChar[16] =
{
    0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
    0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
};
u8 LedBuff[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
u8 KeySta[4] = {1, 1, 1, 1};
u8 TH0RL = 0;
u8 TL0RL = 0;
bit StopWatchRefresh = 1; // 0=不需要刷新,1=需要刷新数码管
u8 DecimalPart = 0;      // 小数部分
u16 IntegerPart = 0;      // 整数部分
bit StopWatchRunning = 0; // 0=停,1=正在工作

void ConfigTimer0(u16 ms)
{
    u32 tmp;
    tmp = 11059200 / 12;
    tmp = tmp * ms / 1000;
    tmp = 65536 - tmp;
    tmp += 18; // 补偿值

    TH0 = TH0RL = (u8)(tmp >> 8);
    TL0 = TL0RL = (u8)tmp;

    TMOD ^= 0xF0;
    TMOD |= 0x01;
    ET0 = TR0 = 1;
}

void StopWatchReset(void)
{
    StopWatchRunning = 0;
    DecimalPart = 0;
    IntegerPart = 0;
    StopWatchRefresh = 1;
}

void StopWatchAction(void)
{
    StopWatchRunning = !StopWatchRunning;
}
void StopWatchCount(void)
{
    if (StopWatchRunning)
    {
        DecimalPart++;
        if (DecimalPart >= 100)
        {
            DecimalPart = 0;
            IntegerPart++;
            if (IntegerPart >= 10000)
            {
                IntegerPart = 0;
            }
        }
        StopWatchRefresh = 1;
    }
}

void StopWatchDisplay(void)
{
    u8 i, j;
    u8 buf[4];

    LedBuff[0] = LedChar[DecimalPart % 10];
    LedBuff[1] = LedChar[DecimalPart / 10];
    buf[0] = IntegerPart % 10;
    buf[1] = IntegerPart / 10 % 10;
    buf[2] = IntegerPart / 100 % 10;
    buf[3] = IntegerPart / 1000 % 10;

    for (i = 3; i >= 1; i--)
    {
        if (buf[i] == 0)
        {
            LedBuff[i + 2] = 0xFF;
        }
        else
        {
            break;
        }
    }
    for (j = 0; j <= i; j++)
    {
        LedBuff[j + 2] = LedChar[buf[j]];
    }
    LedBuff[2] &= 0x7F; // 加小数点
}

void KeyDriver(void)
{
    u8 i;
    static u8 backup[4] = {1, 1, 1, 1};

    for (i = 0; i < 4; i++)
    {
        if (backup[i] != KeySta[i])
        {
            if (backup[i] != 0) // 按下处理
            {
                if (i == 1) // Esc键,复位秒表
                {
                    StopWatchReset();
                }
                else if (i == 2) // 回车键,启停秒表
                {
                    StopWatchAction();
                }
            }
            backup[i] = KeySta[i];
        }
    }
}

void main(void)
{
    EA = 1;
    ENLED = 0;
    ADDR3 = 1;
    P2 = 0xFE; // 1111-1110

    ConfigTimer0(2); // 2ms
    while (1)
    {
        if (StopWatchRefresh)
        {
            StopWatchRefresh = 0;
            StopWatchDisplay();
        }
        KeyDriver();
    }
}

void LedScan(void)
{
    static u8 i = 0;

    P0 = 0xFF;
    P1 = (P1 & 0xF8) | i;
    P0 = LedBuff[i];
    if (i < 5)
        i++;
    else
        i = 0;
}

void KeyScan(void)
{
    static u8 keybuff[4] = {0xFF, 0xFF, 0xFF, 0xFF};
    u8 i;

    keybuff[0] = (keybuff[0] << 1) | KEY1;
    keybuff[1] = (keybuff[1] << 1) | KEY2;
    keybuff[2] = (keybuff[2] << 1) | KEY3;
    keybuff[3] = (keybuff[3] << 1) | KEY4;

    for (i = 0; i < 3; i++)
    {
        if (keybuff[i] == 0xFF)
            KeySta[i] = 1;

        else if (keybuff[i] == 0)
            KeySta[i] = 0;
    }
}

void Timer0_ISR(void) interrupt 1
{
    static u8 tmr10ms = 0;

    TH0 = TH0RL;
    TL0 = TL0RL;
    LedScan();
    KeyScan();

    tmr10ms++;
    if (tmr10ms >= 5)
    {
        tmr10ms = 0;
        StopWatchCount();
    }
}


//跟堂作业,PWM
#include <reg52.h>

typedef unsigned char u8;
typedef unsigned int  u16;
typedef unsigned long u32;
typedef signed char i8;
typedef signed int  i16;
typedef signed long i32;

sbit PWMOUT=P0^0;
sbit ADDR0=P1^0;
sbit ADDR1=P1^1;
sbit ADDR2=P1^2;
sbit ADDR3=P1^3;
sbit ENLED=P1^4;

u8 lowRH,lowRL;
u8 highRH,highRL;

void ConfigPWM( u16 freq, u8 dc )
{
    u32 tmp;
    u16 high,low;

    tmp=11059200/12/freq;//计数值
    high=tmp*dc/100;//高电平计数值
    low=tmp-high;//低电平计数值
    
    high=65536-high+12;//补偿,初值
    low=65536-low+12;//补偿,初值

    highRH=(u8)(high>>8);
    highRL=(u8)(high);
    lowRH=(u8)(low>>8);
    lowRL=(u8)low;
    TMOD&=0xF0;
    TMOD|=0x01;
    TH0=highRH;
    TL0=highRL;
    ET0=TR0=1;
    PWMOUT=1;
}

void ClosePWM(void)
{
    ET0=TR0=0;
    PWMOUT=1;
}

void main(void)
{
    u16 i;

    EA=1;
    ENLED=0;
    ADDR3=1;
    ADDR2=1;
    ADDR1=1;
    ADDR0=0;

    while(1)
    {
        ConfigPWM(100,10);
        for(i=0;i<40000;i++);
        ConfigPWM(100,40);
        for(i=0;i<40000;i++);
        ConfigPWM(100,90);
        for(i=0;i<40000;i++);
        ClosePWM();
        for(i=0;i<40000;i++);
    }
}

void Timer0_ISR(void) interrupt 1
{
    if(PWMOUT==1)
    {
        TH0=lowRH;
        TL0=lowRL;
        PWMOUT=0;
    }
    else
    {
        TH0=highRH;
        TL0=highRL;
        PWMOUT=1;
    }
}

//跟堂作业,呼吸灯
#include <reg52.h>

typedef unsigned char u8;
typedef unsigned int  u16;
typedef unsigned long u32;
typedef signed char i8;
typedef signed int  i16;
typedef signed long i32;

u8 lowRH,lowRL;
u8 highRH,highRL;
u8 TH1RL,TL1RL;
u32 PeriodCnt;

sbit PWMOUT=P0^0;
sbit ADDR0=P1^0;
sbit ADDR1=P1^1;
sbit ADDR2=P1^2;
sbit ADDR3=P1^3;
sbit ENLED=P1^4;

void ConfigPWM( u16 freq, u8 dc )
{
    u16 high,low;

    PeriodCnt=11059200/12/freq;//计数值
    high=PeriodCnt*dc/100;//高电平计数值
    low=PeriodCnt-high;//低电平计数值

    high=65536-high+12;//补偿,初值
    low=65536-low+12;//补偿,初值

    highRH=(u8)(high>>8);
    highRL=(u8)(high);
    lowRH=(u8)(low>>8);
    lowRL=(u8)low;
    TMOD&=0xF0;
    TMOD|=0x01;
    TH0=highRH;
    TL0=highRL;
    ET0=TR0=1;
    PWMOUT=1;
}
void ConfigTimer1( u16 ms )
{
    u32 tmp;
    
    tmp=11059200/12*ms/1000;
    tmp=65536-tmp;
    tmp+=12;//补偿

    TH1RL=(u8)(tmp>>8);
    TL1RL=(u8)tmp;
    TMOD&=0x0F;
    TMOD|=0x10;
    TH1=TH1RL;
    TL1=TL1RL;
    ET1=TR1=1;
}


void ClosePWM(void)
{
    ET0=TR0=0;
    PWMOUT=1;
}

void main(void)
{
    EA=1;

    ENLED=0;
    ADDR3=1;
    ADDR2=1;
    ADDR1=1;
    ADDR0=0;

    ConfigPWM(100,10);//100Hz,占空比10
    ConfigTimer1(50);//50ms
    while(1);
}

void Timer0_ISR(void) interrupt 1
{
    if(PWMOUT==1)
    {
        TH0=lowRH;
        TL0=lowRL;
        PWMOUT=0;
    }
    else
    {
        TH0=highRH;
        TL0=highRL;
        PWMOUT=1;
    }
}

void AdjuctDutyCycle( u8 dc )
{
    u16 high,low;
    
    high=PeriodCnt*dc/100;//高电平计数值
    low=PeriodCnt-high;//低电平计数值

    high=65536-high+12;//补偿,初值
    low=65536-low+12;//补偿,初值
    highRH=(u8)(high>>8);
    highRL=(u8)(high);
    lowRH=(u8)(low>>8);
    lowRL=(u8)low;
}

void Timer1_ISR(void) interrupt 3
{
    u8 code table[13]={5,18,30,41,51,60,68,75,81,86,90,93,95};
    static bit dir=0;
    static u8 index=0;

    TH1=TH1RL;
    TL1=TL1RL;

    AdjuctDutyCycle(table[index]);
    if(dir==0)
    {
        index++;
        if(index>=12)dir=1;
    }
    else
    {
        index--;
        if(index==0)dir=0;
    }

}

//跟堂作业,交通灯--改进版
#include "reg52.h"

typedef signed char i8;
typedef unsigned char u8;
typedef signed int i16;
typedef unsigned int u16;
typedef signed long i32;
typedef unsigned long u32;

sbit ADDR3 = P1 ^ 3;
sbit ENLED = P1 ^ 4;

u8 code LedChar[] = { // 数码管显示字符转换表
    0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
    0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E};
u8 LedBuff[8] = { // 数码管+独立LED显示缓冲区
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
bit flag1s = 1;
u8 TH0RL = 0;
u8 TL0RL = 0;

void ConfigTimer0(u16 ms);
void TrafficLight();
void main(void)
{
    EA = 1;       // 开总中断
    ENLED = 0; // 使能数码管和LED
    ADDR3 = 1;
    ConfigTimer0(1); // 配置T0定时1ms

    while (1)
    {
        if (flag1s) // 每秒执行一次交通灯刷新
        {
            flag1s = 0;
            TrafficLight();
        }
    }
}

void ConfigTimer0(u16 ms)
{
    unsigned long tmp; // 临时变量

    tmp = 11059200 / 12;          // 定时器计数频率
    tmp = (tmp * ms) / 1000;      // 计算所需的计数值
    tmp = 65536 - tmp;          // 计算定时器重载值
    tmp = tmp + 18;              // 补偿中断响应延时造成的误差
    TH0 = TH0RL = (u8)(tmp >> 8); // 定时器重载值拆分为高低字节
    TL0 = TL0RL = (u8)tmp;
    TMOD &= 0xF0;  // 清零T0的控制位
    TMOD |= 0x01;  // 配置T0为模式1
    ET0 = TR0 = 1; // 使能T0中断 // 启动T0
}
void TrafficLight()
{
#define red 1
#define green 2
#define yello 3
    static u8 color = yello;

#define red_smgPos 0
#define green_smgPos 4
#define yello_smgPos 2
    static u8 smgPos = yello_smgPos;
    static i8 timer = 2;
    static u8 lastLight = red;
    u8 i;

    for (i = 0; i < 6; i++)
    {
        LedBuff[i] = 0xFF;
    }

    timer--;
    LedBuff[smgPos] = LedChar[timer % 10];
    LedBuff[smgPos + 1] = LedChar[timer / 10];

    switch (color)
    {
    case green:
        LedBuff[6] = 0x3F; // 0011-1111
        if (timer == 0)
        {
            lastLight = green;
            smgPos = yello_smgPos;
            color = yello;
            timer = 2;
        }
        break;
    case yello:
        LedBuff[6] = 0xE7; // 1110-0111
        if (timer == 0)
        {
            if (lastLight == green)
            {
                color = red;
                smgPos = red_smgPos;
                timer = 10;
            }
            else if (lastLight == red)
            {
                color = green;
                smgPos = green_smgPos;
                timer = 20;
            }
        }
        break;
    case red:
        LedBuff[6] = 0xFC; // 1111-1100
        if (timer == 0)
        {
            lastLight = red;
            smgPos = yello_smgPos;
            color = yello;
            timer = 2;
        }
        break;
    }
}
void LedScan()
{
    static u8 i = 0; // 动态扫描索引

    P0 = 0xFF;          // 关闭所有段选位,显示消隐
    P1 = (P1 & 0xF8) | i; // 位选索引值赋值到P1口低3位
    P0 = LedBuff[i];      // 缓冲区中索引位置的数据送到P0口
    i++;
    i &= 0x07; // 0000-0111
}

void InterruptTimer0() interrupt 1
{
    static u16 tmr1s = 0; // 1秒定时器

    TH0 = TH0RL; // 重新加载重载值
    TL0 = TL0RL;

    LedScan(); // LED扫描显示
    tmr1s++;   // 1秒定时的处理
    if (tmr1s >= 1000)
    {
        tmr1s = 0;
        flag1s = 1; // 设置秒定时标志
    }
}


//跟堂作业 c4炸弹
#include <reg52.h>

typedef signed char i8;
typedef unsigned char u8;
typedef signed int i16;
typedef unsigned int u16;
typedef signed long i32;
typedef unsigned long u32;

sbit BUZZ = P1 ^ 6;
sbit ADDR3 = P1 ^ 3;
sbit ENLED = P1 ^ 4;

sbit KEYIN1 = P2 ^ 4;
sbit KEYIN2 = P2 ^ 5;
sbit KEYIN3 = P2 ^ 6;
sbit KEYIN4 = P2 ^ 7;
sbit KEYOUT1 = P2 ^ 3;
sbit KEYOUT2 = P2 ^ 2;
sbit KEYOUT3 = P2 ^ 1;
sbit KEYOUT4 = P2 ^ 0;

u8 code LedChar[16] =
    {
    0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
    0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E};
u8 LedBuff[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
u8 code KeyCodeMap[4][4] =
    {
    {0x31, 0x32, 0x33, 0x26}, // 数字1,2,3,UP
    {0x34, 0x35, 0x36, 0x25}, // 数字4,5,6,LEFT
    {0x37, 0x38, 0x39, 0x28}, // 数字7,8,9,DOWN
    {0x30, 0x1B, 0x0D, 0x27}, // 数字0,ESC,ENTER,RIGHT

};
u8 KeySta[4][4] = {{1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}};

u32 pdata KeyDownTime[4][4] = {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}};

bit enBuzz = 0;
bit flag1s = 0;
bit flagStart = 0;

u8 TH0RL = 0;
u8 TL0RL = 0;
u16 CountDown = 0;

void ConfigTimer0(u16 ms)
{
    u32 tmp;
    tmp = 11059200 / 12;
    tmp = tmp * ms / 1000;
    tmp = 65536 - tmp;
    tmp += 18; // 补偿值

    TH0 = TH0RL = (u8)(tmp >> 8);
    TL0 = TL0RL = (u8)tmp;

    TMOD &= 0xF0;
    TMOD |= 0x01;
    ET0 = TR0 = 1;
}

void ShowNumber(u32 num)
{
    i8 i;
    u8 buf[6];

    for (i = 0; i < 6; i++)
    {
        buf[i] = num % 10;
        num /= 10;
    }
    for (i = 5; i >= 1; i--)
    {
        if (buf[i] == 0)
            LedBuff[i] = 0xFF;
        else
            break;
    }
    for (; i >= 0; i--)
    {
        LedBuff[i] = LedChar[buf[i]];
    }
}

void KeyAction(u8 keycode)
{
    if (keycode == 0x26) // up
    {
        if (CountDown < 9999)
        {
            CountDown++;
            ShowNumber(CountDown);
        }
    }
    else if (keycode == 0x28) // down
    {
        if (CountDown > 1)
        {
            CountDown--;
            ShowNumber(CountDown);
        }
    }
    else if (keycode == 0x0D) // enter
    {
        flagStart = 1;
    }
    else if (keycode == 0x1B) // esc
    {
        enBuzz = 0;
        LedBuff[6] = 0xFF;
        flagStart = 0;
        CountDown = 0;
        ShowNumber(CountDown);
    }
}

void KeyDriver(void)
{
    u8 i, j;
    static u8 backup[4][4] = {{1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}};
    static u32 pdata TimeThr[4][4] = {
        {1000, 1000, 1000, 1000},
        {1000, 1000, 1000, 1000},
        {1000, 1000, 1000, 1000},
        {1000, 1000, 1000, 1000}};

    for (i = 0; i < 4; i++)
    {
        for (j = 0; j < 4; j++)
        {
            if (backup[i][j] != KeySta[i][j])
            {
                if (backup[i][j] == 0)
                {
                    KeyAction(KeyCodeMap[i][j]);
                }
                backup[i][j] = KeySta[i][j];
            }
            if (KeyDownTime[i][j] > 0)
            {
                if (KeyDownTime[i][j] >= TimeThr[i][j])
                {
                    KeyAction(KeyCodeMap[i][j]);
                    TimeThr[i][j] += 200;
                }
            }
            else
            {
                TimeThr[i][j] = 1000;
            }
        }
    }
}

void main(void)
{
    EA = 1;
    ENLED = 0;
    ADDR3 = 1;

    ConfigTimer0(1); // 1ms
    ShowNumber(0);
    while (1)
    {
        KeyDriver();
        if (flagStart && flag1s)
        {
            flag1s = 0;
            if (CountDown > 0)
            {
                CountDown--;
                ShowNumber(CountDown);
                if (CountDown == 0)
                {
                    enBuzz = 1;
                    LedBuff[6] = 0;
                }
            }
        }
    }
}

void LedScan(void)
{
    static u8 i = 0;

    P0 = 0xFF;
    P1 = (P1 & 0xF8) | i;
    P0 = LedBuff[i];
    i++;
    i &= 0x07; // 0000-0111
}
void KeyScan(void)
{
    u8 i;
    static u8 keyout = 0;
    static u8 keybuf[4][4] = {{0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}};

    keybuf[keyout][0] = (keybuf[keyout][0] << 1) | KEYIN1;
    keybuf[keyout][1] = (keybuf[keyout][1] << 1) | KEYIN2;
    keybuf[keyout][2] = (keybuf[keyout][2] << 1) | KEYIN3;
    keybuf[keyout][3] = (keybuf[keyout][3] << 1) | KEYIN4;

    for (i = 0; i < 4; i++)
    {
        if ((keybuf[keyout][i] & 0x0F) == 0)
        {
            KeySta[keyout][i] = 0;
            KeyDownTime[keyout][i] += 4;
        }
        else if ((keybuf[keyout][i] & 0x0F) == 0x0F)
        {
            KeySta[keyout][i] = 1;
            KeyDownTime[keyout][i] = 0;
        }
    }
    keyout++;
    keyout &= 0x03; // 0000-0011
    switch (keyout)
    {
    case 0:    KEYOUT4 = 1; KEYOUT1 = 0; break;
    case 1: KEYOUT1 = 1; KEYOUT2 = 0; break;
    case 2: KEYOUT2 = 1; KEYOUT3 = 0; break;
    case 3: KEYOUT3 = 1; KEYOUT4 = 0; break;
    }
}

void Timer0_ISR(void) interrupt 1
{
    static u16 tmr1s = 0;

    TH0 = TH0RL;
    TL0 = TL0RL;

    if (enBuzz)
        BUZZ = !BUZZ;
    else
        BUZZ = 1;

    LedScan();
    KeyScan();
    if (flagStart)
    {
        tmr1s++;
        if (tmr1s >= 1000)
        {
            tmr1s = 0;
            flag1s = 1;
        }
    }
    else
    {
        tmr1s = 0;
    }
}


第10章-实例练习与经验积累(上:跟堂作业)的评论 (共 条)

分享到微博请遵守国家法律