一、题目说明:
二、代码实现:
mian.c文件
#include <STC15F2K60S2.H>
#include "port.h"
#include "key.h"
#include "AT24C02.h"
#include "led.h"
#define u8 unsigned char
#define u16 unsigned int
u8 code t_display[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00,0x40};
u8 code T_COM[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
u8 menu[][8] = {{10, 10, 10, 10, 10, 10, 10, 10}, {11, 1, 11, 10, 10, 10, 0, 0}};
u8 Trg, Com, index, LEDtime[5] = {4, 4, 4, 4}, mode = 0;
u16 t2_cnt;
bit keyflag, tick_100ms;
void Timer2Init(void) //1毫秒@11.0592MHz
{
AUXR |= 0x04; //定时器时钟1T模式
T2L = 0xCD; //设置定时初值
T2H = 0xD4; //设置定时初值
AUXR |= 0x10; //定时器2开始计时
IE2 |= 0x04; //开定时器2中断
}
void t2int() interrupt 12 //中断入口
{
static u8 i;
u8 key_val;
LED_Com(0x00);
LED_Bit(T_COM[i]);
LED_Com(t_display[menu[index][i]]);
if(++i == 8)
i = 0;
if(t2_cnt % 20 == 0)
{
key_val = KeyScan();
Trg = key_val & (key_val ^ Com);
Com = key_val;
if(Trg != 0)
keyflag = 1;
if(Com == 4)
{
menu[0][6] = 11;
menu[0][7] = brightness + 1;
}
else
{
menu[0][6] = 10;
menu[0][7] = 10;
}
}
if(t2_cnt % 100 == 0)
tick_100ms = 1;
if(++t2_cnt == 1000)
{
t2_cnt = 0;
}
}
void main(void)
{
u8 setbit, cnt_100ms, runmode, i, blink_cnt;
bit ledrun, blink_bit;
Relay(0);
Buzzer(0);
LED(0x00);
for(i = 0; i < 4; ++i)
{
// AT24C02_WriteData(i, LEDtime[i]);
LEDtime[i] = AT24C02_ReadData(i);
}
Timer0Init();
Timer2Init();
EA = 1;
while(1)
{
if(keyflag)
{
keyflag = 0;
switch(Trg)
{
case 4:
{
if(index != 0)
{
if(setbit == 1)
runmode = (runmode + 3) % 4;
else if(setbit == 2)
{
if(LEDtime[runmode] > 4)
LEDtime[runmode]--;
}
}
break;
}
case 5:
{
if(index != 0)
{
if(setbit == 1)
runmode = (runmode + 1) % 4;
else if(setbit == 2)
{
if(LEDtime[runmode] < 12)
LEDtime[runmode]++;
}
}
break;
}
case 6:
{
if(index == 0)
index = 1;
else
{
setbit++;
if(setbit == 3)
{
index = 0;
setbit = 0;
TR0 = 0;
AT24C02_WriteData(runmode, LEDtime[runmode]);
TR0 = 1;
}
}
break;
}
case 7:
{
ledrun = ~ledrun;
break;
}
}
}
if(tick_100ms)
{
tick_100ms = 0;
++cnt_100ms;
if(LEDtime[mode] == cnt_100ms)
{
if(ledrun)//利用按键标志位来控制灯的开始与停止
mode = LEDMode() - 1;
cnt_100ms = 0;
}
if(index == 1)
{
if(blink_bit)
{
if(setbit == 1)
menu[1][1] = 10;
else if(setbit == 2)
{
menu[1][4] = 10;
menu[1][5] = 10;
menu[1][6] = 10;
menu[1][7] = 10;
}
}
else
{
menu[1][1] = runmode + 1;
menu[1][4] = LEDtime[runmode] / 10;
menu[1][5] = LEDtime[runmode] % 10;
menu[1][6] = 0;
menu[1][7] = 0;
if(menu[1][4] == 0)
menu[1][4] = 10;
}
}
if((index == 1) && (++blink_cnt % 8 == 0))
{
blink_cnt = 0;
blink_bit = ~blink_bit;
}
}
}
}
port.c文件
#include "port.h"
#include <STC15F2K60S2.H>
#include <intrins.h>
unsigned char bdata control;
sbit relay = control^4;
sbit buzzer = control^6;
void Relay(unsigned char k)
{
relay = k;
P0 = control;
P2 = 0xa0;
_nop_();
P2 = 0x00;
}
void Buzzer(unsigned char k)
{
buzzer = k;
P0 = control;
P2 = 0xa0;
_nop_();
P2 = 0x00;
}
void LED(unsigned char k)
{
P0 = ~k;
P2 = 0x80;
_nop_();
P2 = 0x00;
}
void LED_Bit(unsigned char k)
{
P0 = k;
P2 = 0xc0;
_nop_();
P2 = 0x00;
}
void LED_Com(unsigned char k)
{
P0 = ~k;
P2 = 0xe0;
_nop_();
P2 = 0x00;
}
key.c文件
#include "key.h"
#include <STC15F2K60S2.H>
#include <intrins.h>
void Delay100us() //@11.0592MHz
{
unsigned char i, j;
_nop_();
_nop_();
i = 2;
j = 15;
do
{
while (--j);
} while (--i);
}
unsigned char KeyScan(void)
{
if(P33 == 0)
{
Delay100us();
if(P33 == 0)
return 4;
}
else if(P32 == 0)
{
Delay100us();
if(P32 == 0)
return 5;
}
else if(P31 == 0)
{
Delay100us();
if(P31 == 0)
return 6;
}
else if(P30 == 0)
{
Delay100us();
if(P30 == 0)
return 7;
}
return 0;
}
iic.c文件
/*
³ÌÐò˵Ã÷: IIC×ÜÏßÇý¶¯³ÌÐò
Èí¼þ»·¾³: Keil uVision 4.10
Ó²¼þ»·¾³: CT107µ¥Æ¬»ú×ÛºÏʵѵƽ̨ 8051£¬12MHz
ÈÕ ÆÚ: 2011-8-9
*/
#include "reg52.h"
#include "intrins.h"
#include "iic.h"
#define DELAY_TIME 3
#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1
//×ÜÏßÒý½Å¶¨Òå
sbit SDA = P2^1; /* Êý¾ÝÏß */
sbit SCL = P2^0; /* ʱÖÓÏß */
void IIC_Delay(unsigned char i)
{
do{_nop_();_nop_();_nop_();}
while(i--);
}
//×ÜÏßÆô¶¯Ìõ¼þ
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 0;
}
//×ÜÏßÍ£Ö¹Ìõ¼þ
void IIC_Stop(void)
{
SDA = 0;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 1;
IIC_Delay(DELAY_TIME);
}
//·¢ËÍÓ¦´ð
void IIC_SendAck(bit ackbit)
{
SCL = 0;
SDA = ackbit; // 0£ºÓ¦´ð£¬1£º·ÇÓ¦´ð
IIC_Delay(DELAY_TIME);
SCL = 1;
IIC_Delay(DELAY_TIME);
SCL = 0;
SDA = 1;
IIC_Delay(DELAY_TIME);
}
//µÈ´ýÓ¦´ð
bit IIC_WaitAck(void)
{
bit ackbit;
SCL = 1;
IIC_Delay(DELAY_TIME);
ackbit = SDA;
SCL = 0;
IIC_Delay(DELAY_TIME);
return ackbit;
}
//ͨ¹ýI2C×ÜÏß·¢ËÍÊý¾Ý
void IIC_SendByte(unsigned char byt)
{
unsigned char i;
for(i=0; i<8; i++)
{
SCL = 0;
IIC_Delay(DELAY_TIME);
if(byt & 0x80) SDA = 1;
else SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 1;
byt <<= 1;
IIC_Delay(DELAY_TIME);
}
SCL = 0;
}
//´ÓI2C×ÜÏßÉϽÓÊÕÊý¾Ý
unsigned char IIC_RecByte(void)
{
unsigned char i, da;
for(i=0; i<8; i++)
{
SCL = 1;
IIC_Delay(DELAY_TIME);
da <<= 1;
if(SDA) da |= 1;
SCL = 0;
IIC_Delay(DELAY_TIME);
}
return da;
}
AT24C02.c文件
#include "iic.h"
#include "AT24C02.h"
#include <intrins.h>
void Delay4ms() //@11.0592MHz
{
unsigned char i, j;
_nop_();
i = 44;
j = 4;
do
{
while (--j);
} while (--i);
}
void AT24C02_WriteData(unsigned char addr, unsigned char dat)
{
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
Delay4ms();
}
unsigned char AT24C02_ReadData(unsigned char addr)
{
unsigned char dat;
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0xa1);
IIC_WaitAck();
dat = IIC_RecByte();
IIC_SendAck(1);
IIC_Stop();
Delay4ms();
return dat;
}
pcf.c文件
#include "pcf.h"
#include "iic.h"
unsigned char GetVoltage(void)
{
unsigned char dat;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x43);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
dat = IIC_RecByte();
IIC_SendAck(1);
IIC_Stop();
return dat;
}
led.c文件
#include "led.h"
#include <STC15F2K60S2.H>
#include <intrins.h>
#include "pcf.h"
#include "port.h"
unsigned char PWMState;
unsigned char brightness;
unsigned int t0_cnt;
unsigned char highcnt[4] = {10, 40, 80, 160};
unsigned char shift = 0x01;
unsigned char tmp = 0x00;
unsigned char LEDMode(void)
{
static unsigned char mode = 1;
P0 = ~shift;
PWMState = shift;
tmp = shift;
P2 = 0x80;
_nop_();
P2 = 0x00;
if(mode == 1)
{
shift <<= 1;
if(PWMState == 0xff)
{
shift = 0x80;
PWMState = 0x00;
mode = 2;
}
}
else if(mode == 2)
{
shift >>= 1;
if(PWMState == 0xff)
{
shift = 0x81;
PWMState = 0x00;
mode = 3;
}
}
else if(mode == 3)
{
shift = ((shift >> 1) & 0xf0) | ((shift << 1) & 0x0f);
if(PWMState == 0xff)
{
shift = 0x18;
PWMState = 0x00;
mode = 4;
}
}
else if(mode == 4)
{
shift = ((shift << 1) & 0xf0) | ((shift >> 1) & 0x0f);
if(PWMState == 0xff)
{
shift = 0x01;
PWMState = 0x00;
mode = 1;
}
}
shift = shift | PWMState;
return mode;
}
void Timer0Init(void) //1000微秒@11.0592MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xae; //设置定时初值
TH0 = 0xfb; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
}
//定时器0中断服务程序
void tm0() interrupt 1
{
static unsigned char PWMCnt;
if(++t0_cnt == 200)
{
brightness = GetVoltage() / 64;
t0_cnt = 0;
}
PWMCnt++;
PWMCnt = PWMCnt % 201;
if(PWMCnt < highcnt[brightness])
LED(tmp);
else
LED(0x00);
}
三、代码说明:
- 这道题目写了好久,一开始卡的点是灯是怎么点亮的,是点一个灭一个还是点完就不灭了,所以才设置了PWMState这个标志位,来记录灯的前一个状态。调节灯的亮度使用的是定时器产生PWM波。
2、整体代码最后还是有两个警告,但在板子上运行并没有看到不符合实验的现象。