1.1 使用 CT107D 单片机竞赛板,完成“彩灯控制器” 功能的程序设计与调试;
1.2 设计与调试过程中,可参考组委会提供的“资源数据包”;
1.3 Keil 工程文件以准考证号命名,完成设计后,提交完整、可编译的 Keil工程文件到服务器。
3.1 基本功能描述
通过单片机控制 8 个 LED 指示灯按照特定的顺序(工作模式) 亮灭; 指示灯的流转间隔可通过按键调整,亮度可由电位器 RB2 进行控制; 各工作模式的流转间隔时间需在 E2PROM 中保存,并可在硬件重新上电后,自动载入。
3.2 设计说明
(1)关闭蜂鸣器、继电器等与本试题程序设计无关的外设资源
(2)设备上电后默认数码管、 LED 指示灯均为熄灭状态;
(3)流转间隔可调整范围为 400ms-1200ms;
(4)设备固定按照模式 1、模式 2、模式 3、 模式 4 的次序循环往复运行。
3.3 LED 指示灯工作模式
(1)模式 1: 按照 L1、 L2…L8 的顺序, 从左到右单循环点亮。
(2)模式 2: 按照 L8、 L7…L1 的顺序, 从右到左单循环点亮。
(3)模式 3:
(4)模式4:
3.4 亮度等级控制
检测电位器 RB2 的输出电压,控制 8 个 LED 指示灯的亮度,要求在 0V-5V的可调区间内,实现 4 个均匀分布的 LED 指示灯亮度等级。
3.5 按键功能
(1)按键 S7 定义为“启动/停止”按键,按下后启动或停止 LED 的流转。
(2)按键 S6 定义为“设置”按键,按键按下后数码管进入“流转间隔”设置界面,如下图所示:
通过按键 S6 可切换选择“运行模式” 和“流转间隔” 两个显示单元,当前被选择的显示单元以 0.8 秒为间隔亮灭。
(3)按键 S5 定义为“加”按键,在设置界面下,按下该键,若当前选择的是运行模式,则运行模式编号加 1,若当前选择的是流转间隔,则流转间隔增加 100ms。
(4)按键 S4 定义为“减”按键,在设置界面下,按下该键,若当前选择的是运行模式,则运行模式编号减 1,若当前选择的是流转间隔,则流转间隔减少 100ms。
(5)按键功能说明:
(a)按键 S4、 S5 的“ 加”、 “ 减” 功能只在“设置状态”下有效,数值的调整应注意边界属性。
(b)在非“设置状态”下,按下 S4 按键可显示指示灯当前的亮度等级, 4 个亮度等级从暗到亮,依次用数字 1、 2、 3、 4 表示; 松开S4 按键,数码管显示关闭, 亮度等级的显示格式如下图所示:
模拟输入:要掌握PCF8591芯片上的AD转换。
按键控制:S7(P30),S6(P31),S5(P32),S4(P33)。
LED指示灯:初始化、P0端口低电平亮。
IIC总线控制、数码管显示。
E2PROM读取断电后的数据。
最后是PWM脉冲宽度调制技术控制led的亮度。对于PWM的解释可见博客:
https://blog.csdn.net/fanjufei123456/article/details/105025590
还有一些细节上的连接问题,需要自己动手操作。
蓝桥杯第九届省赛和第八届省赛,赛题还是比较相似的,按键控制方式都基本上一样的模式,第八届有实时时钟、温度传感器等,第九届是AD、IIC总线、EEPROM、PWM控制,另外PWM可能是个问题点。
iic.c
#include "iic.h"
//总线启动条件
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
somenop;
SDA = 0;
somenop;
SCL = 0;
}
//总线停止条件
void IIC_Stop(void)
{
SDA = 0;
SCL = 1;
somenop;
SDA = 1;
}
//等待应答
bit IIC_WaitAck(void)
{
SDA = 1;
somenop;
SCL = 1;
somenop;
if(SDA)
{
SCL = 0;
IIC_Stop();
return 0;
}
else
{
SCL = 0;
return 1;
}
}
//通过I2C总线发送数据
void IIC_SendByte(unsigned char byt)
{
unsigned char i;
for(i=0;i<8;i++)
{
if(byt&0x80)
{
SDA = 1;
}
else
{
SDA = 0;
}
somenop;
SCL = 1;
byt <<= 1;
somenop;
SCL = 0;
}
}
//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
unsigned char da;
unsigned char i;
for(i=0;i<8;i++)
{
SCL = 1;
somenop;
da <<= 1;
if(SDA)
da |= 0x01;
SCL = 0;
somenop;
}
return da;
}
unsigned char AD_Read(unsigned char add)
{
unsigned char temp;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_Stop();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
temp=IIC_RecByte();
IIC_Stop();
return temp;
}
//EEPROM读
unsigned char EEPROM_Read(unsigned char add)
{
unsigned char temp;
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_Stop();
IIC_Start();
IIC_SendByte(0xa1);
IIC_WaitAck();
temp=IIC_RecByte();
IIC_Stop();
return temp;
}
//EEPROMD写
void EEPROM_Write(unsigned char dat,unsigned char add)
{
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}
iic.h
#ifndef _IIC_H
#define _IIC_H
#include "stc15f2k60s2.h"
#include "intrins.h"
#define somenop {_nop_();_nop_();_nop_();_nop_();_nop_();}
#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1
//总线引脚定义
sbit SDA = P2^1; /* 数据线 */
sbit SCL = P2^0; /* 时钟线 */
//函数声明
void IIC_Start(void);
void IIC_Stop(void);
void IIC_Ack(unsigned char ackbit);
void IIC_SendByte(unsigned char byt);
bit IIC_WaitAck(void);
unsigned char IIC_RecByte(void);
unsigned char AD_Read(unsigned char add);
unsigned char EEPROM_Read(unsigned char add);
void EEPROM_Write(unsigned char dat,unsigned char add);
#endif
text.c
#include
#include "iic.h"
#define uchar unsigned char
#define uint unsigned int
uchar code tab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF};
uchar start=0;
uchar moshi=1;
uchar zhuanhua=0;
uint jiange=400;
uint led_t=0;
uint zhuanhua_t=0;
uint ad_t=0;
uint RB2=0;
uchar flag=0;
uchar led_n=0;
uchar led_TT=0,light=0;
uchar f1,f2,f3,f4,f5,f6,f7,f8;
void allinit();
void delayms(uchar ms);
void keyscan();
void Time0_init();
void display12(uchar f1,uchar f2);
void display34(uchar f3,uchar f4);
void display56(uchar f5,uchar f6);
void display78(uchar f7,uchar f8);
void main(){
allinit();
Time0_init();
moshi=EEPROM_Read(0x10);
delayms(5);
jiange=EEPROM_Read(0x20)*100;
delayms(5);
f1=11;f2=11;f3=11;f4=11;f5=11;f6=11;f7=11;f8=11;
while(1){
if((zhuanhua==0)&&(flag==1))
{
if(RB2<64)
{
f1=11;f2=11;f3=11;f4=11;f5=11;f6=11;f7=10;f8=1;
}
else if((RB2>=64)&&(RB2<128))
{
f1=11;f2=11;f3=11;f4=11;f5=11;f6=11;f7=10;f8=2;
}
else if((RB2>=128)&&(RB2<192))
{
f1=11;f2=11;f3=11;f4=11;f5=11;f6=11;f7=10;f8=3;
}
else if((RB2>=192)&&(RB2<255))
{
f1=11;f2=11;f3=11;f4=11;f5=11;f6=11;f7=10;f8=4;
}
}
else if(zhuanhua==0)
{
f1=11;f2=11;f3=11;f4=11;f5=11;f6=11;f7=11;f8=11;
}
keyscan();
display12(f1,f2);
display34(f3,f4);
display56(f5,f6);
display78(f7,f8);
}
}
void keyscan(){
if(P30==0)
{
delayms(5);
if(P30==0)
{
if(start==0)
{
start=1;
}
else if(start==1)
{
start=0;
}
}
while(!P30);
}
else if(P31==0)
{
delayms(5);
if(P31==0)
{
if(zhuanhua==0)
{
zhuanhua=1;zhuanhua_t=0;
if(jiange>=1000)
{
f1=10;f2=moshi;f3=10;f4=11;f5=jiange/1000;f6=jiange%1000/100;f7=jiange%100/10;f8=jiange%10;
}
else
{
f1=10;f2=moshi;f3=10;f4=11;f5=11;f6=jiange/100;f7=jiange%100/10;f8=jiange%10;
}
}
else if(zhuanhua==1)
{
zhuanhua=2;zhuanhua_t=0;
if(jiange>=1000)
{
f1=10;f2=moshi;f3=10;f4=11;f5=jiange/1000;f6=jiange%1000/100;f7=jiange%100/10;f8=jiange%10;
}
else
{
f1=10;f2=moshi;f3=10;f4=11;f5=11;f6=jiange/100;f7=jiange%100/10;f8=jiange%10;
}
}
else if(zhuanhua==2)
{
zhuanhua=0;zhuanhua_t=0;
f1=11;f2=11;f3=11;f4=11;f5=11;f6=11;f7=11;f8=11;
EEPROM_Write(moshi,0x10);
delayms(5);
EEPROM_Write(jiange/100,0x20);
delayms(5);
}
}
while(!P31);
}
else if(P32==0)
{
delayms(5);
if(P32==0)
{
if(zhuanhua==1)
{
moshi+=1;
if(moshi==5)
{
moshi=1;
}
}
else if(zhuanhua==2)
{
jiange+=100;
if(jiange==1300)
{
jiange=400;
}
}
}
while(!P32);
}
else if(P33==0)
{
delayms(5);
if(P33==0)
{
flag=1;
}
}
if((P33==1)&&(flag==1))
{
flag=0;
if(zhuanhua==1)
{
moshi-=1;
if(moshi==0)
{
moshi=4;
}
}
else if(zhuanhua==2)
{
jiange-=100;
if(jiange==300)
{
jiange=1200;
}
}
}
}
void Time0_init(){
TMOD=0X01;
TH0=(65536-1000)/256;
TL0=(65536-1000)%256;
TR0=1;
EA=1;
ET0=1;
}
void Time0_service() interrupt 1
{
TH0=(65536-1000)/256;
TL0=(65536-1000)%256;
zhuanhua_t++;
led_t++;
ad_t++;
if((led_t==1)&&(start==1))
{
if(moshi==1)
{
P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;
P0=~(0X01<>led_n);
}
else if(moshi==3)
{
P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;
if(led_n==0) P0=0X7E;
else if(led_n==1) P0=0XBD;
else if(led_n==2) P0=0XDB;
else if(led_n==3) P0=0XE7;
}
else if(moshi==4)
{
P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;
if(led_n==0) P0=0XE7;
else if(led_n==1) P0=0XDB;
else if(led_n==2) P0=0XBD;
else if(led_n==3) P0=0X7E;
}
}
else if(led_t==light)
{
P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;
}
else if(led_t==20)
{
led_t=0;led_TT++;
if(20*led_TT>=jiange)
{
led_TT=0;
if(moshi==1)
{
led_n++;
if(led_n>=8)
{
led_n=0;
}
}
else if(moshi==2)
{
led_n++;
if(led_n>=8)
{
led_n=0;
}
}
else if(moshi==3)
{
led_n++;
if(led_n>=4)
{
led_n=0;
}
}
else if(moshi==4)
{
led_n++;
if(led_n>=4)
{
led_n=0;
}
}
}
}
if(ad_t==200)
{
ad_t=0;
RB2=AD_Read(0x03);
if(RB2<64) light=2;
else if((RB2>=64)&&(RB2<128)) light=5;
else if((RB2>=128)&&(RB2<192)) light=10;
else if((RB2>=192)&&(RB2<255)) light=19;
}
if(zhuanhua_t==800)
{
if(zhuanhua==1)
{
if(jiange>=1000)
{
f1=11;f2=11;f3=11;f4=11;f5=jiange/1000;f6=jiange%1000/100;f7=jiange%100/10;f8=jiange%10;
}
else
{
f1=11;f2=11;f3=11;f4=11;f5=11;f6=jiange/100;f7=jiange%100/10;f8=jiange%10;
}
}
else if(zhuanhua==2)
{
if(jiange>=1000)
{
f1=10;f2=moshi;f3=10;f4=11;f5=11;f6=11;f7=11;f8=11;
}
else
{
f1=10;f2=moshi;f3=10;f4=11;f5=11;f6=11;f7=11;f8=11;
}
}
}
if(zhuanhua_t==1600)
{
zhuanhua_t=0;
if(zhuanhua==1)
{
if(jiange>=1000)
{
f1=10;f2=moshi;f3=10;f4=11;f5=jiange/1000;f6=jiange%1000/100;f7=jiange%100/10;f8=jiange%10;
}
else
{
f1=10;f2=moshi;f3=10;f4=11;f5=11;f6=jiange/100;f7=jiange%100/10;f8=jiange%10;
}
}
else if(zhuanhua==2)
{
if(jiange>=1000)
{
f1=10;f2=moshi;f3=10;f4=11;f5=jiange/1000;f6=jiange%1000/100;f7=jiange%100/10;f8=jiange%10;
}
else
{
f1=10;f2=moshi;f3=10;f4=11;f5=11;f6=jiange/100;f7=jiange%100/10;f8=jiange%10;
}
}
}
}
void allinit(){
P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;
P2=0XC0;P0=0XFF;P2=0XFF;P0=0XFF;
}
void delayms(uchar ms){
uchar i,j,k;
for(k=ms;k>0;k--){
i=12;
j=169;
do
{
while(j--);
}
while(i--);
}
}
void display12(uchar f1,uchar f2){
P2=0XC0;P0=0X01;P2=0XFF;P0=tab[f1];
delayms(1);
P2=0XC0;P0=0X02;P2=0XFF;P0=tab[f2];
delayms(1);
}
void display34(uchar f3,uchar f4){
P2=0XC0;P0=0X04;P2=0XFF;P0=tab[f3];
delayms(1);
P2=0XC0;P0=0X08;P2=0XFF;P0=tab[f4];
delayms(1);
}
void display56(uchar f5,uchar f6){
P2=0XC0;P0=0X10;P2=0XFF;P0=tab[f5];
delayms(1);
P2=0XC0;P0=0X20;P2=0XFF;P0=tab[f6];
delayms(1);
}
void display78(uchar f7,uchar f8){
P2=0XC0;P0=0X40;P2=0XFF;P0=tab[f7];
delayms(1);
P2=0XC0;P0=0X80;P2=0XFF;P0=tab[f8];
delayms(1);
}