第10章-实例练习与经验积累(上:跟堂作业)
这节课,真没意思,不想做,拖了好几天,快没感觉了
//跟堂作业:秒表
#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;
}
}