1. 比赛题目要求
2. 功能实现推荐步骤
首先,添加头文件,搭建最底层的代码,实现基本的流水灯运转与数码管显示rb2的电阻值
然后,进行pwm脉宽调制,实现rb2数值不同,从而灯光亮度不同。并作出数码管的多窗口切换
接着,完成4个独立按键的功能配置,每写一个按键,就把一个按键的功能完善好
再是,测试数码管的显示效果,这个至关重要,保证每个数码管显示效果较好
最后,编写24c02的程序
3. 各个功能模块实现思路
以下内容由chatgpt4.0生成:
-
PWM调节亮度相关变量:
pwm_50us
:用于产生PWM信号的基础时间计数器,每50微秒增加一次。pwm_duty
:PWM占空比控制变量,决定LED亮度级别。value_led
:传入P0口的LED的亮度数值
-
数码管闪烁与动态显示相关变量:
SMG_flag
:数码管窗口切换标志位,控制数码管是显示LED亮度值还是流水灯的速度。flash_count
:用于控制数码管刷新的计数器。
-
数码管显示窗口切换相关变量:
key6_state
:用于控制数码管显示内容切换的按键状态变量,其值改变时会切换显示内容。if_800ms
:控制数码管是否闪烁的标志,以800ms为周期。
-
模拟信号读取相关变量:
rb2_value
:存储从模拟转换器读取的模拟值,该值用于根据模拟信号的大小调节LED灯的亮度。
-
LED流水灯控制相关变量:
led_move
:控制LED流水灯流动的计数器。led_mode_value
:LED模式值,决定了LED灯亮度调节的模式。
程序中,通过定时器init_timer0
和init_timer1
的设置,实现了基于时间的任务调度,如PWM信号的生成、数码管的动态显示和闪烁等。数码管的具体显示由state_SMG
和state_SMG_all
函数控制,通过这些函数可以将要显示的数字或模式对应的码传送到数码管上显示。而valuerunning
函数则根据模拟信号(通过rb2_value
读取)调整PWM占空比(pwm_duty
),进而调节LED亮度。此外,通过按键的检测(keyrunning
函数),用户可以切换显示模式和调整亮度或流水灯速度。
4. 代码参考
/**
该代码为蓝桥杯单片机组第九届省赛程序——彩灯控制器
作者:archie474:CSDN
欢迎在博客中留言代码中的问题,以及存在的疑惑
*/
#include <reg52.h>
#include <intrins.h>
#include <absacc.h>
#include <iic.h>
sbit AUXR = 0x8e;
sbit S7 = P3^0;
sbit S6 = P3^1;
sbit S5 = P3^2;
sbit S4 = P3^3;
unsigned char code duanma[18] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
0x88,0x83,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};
unsigned char code ledmode2[8] = { 0x7f , 0xbf , 0xdf , 0xef , 0xf7 , 0xfb , 0xfd , 0xfe };
unsigned char code ledmode1[8] = { 0xfe , 0xfd , 0xfb , 0xf7 , 0xef , 0xdf , 0xbf , 0x7f };
unsigned char code ledmode3[4] = { 0x7e , 0xbd , 0xdb , 0xe7 };
unsigned char code ledmode4[4] = { 0xe7 , 0xdb , 0xbd , 0x7e };
unsigned char sys_stop = 0;
unsigned char pwm_50us = 0;
unsigned char pwm_5ms = 0;
unsigned char pwm_duty = 0;
unsigned char value_led = 0;
bit led_stop = 0;
unsigned char key6_state = 0;
bit key5_state = 0;
bit key4_state = 0;
void SMG_flashing ();
void save_data();
void state_SMG ( unsigned char pos_SMG , unsigned char value_SMG )
{
XBYTE[0xe000] = 0xff;
XBYTE[0xc000] = 0x01 << pos_SMG;
XBYTE[0xe000] = value_SMG;
}
void state_SMG_all ( unsigned char value_SMG_all )
{
XBYTE[0xc000] = 0xff;
XBYTE[0xe000] = value_SMG_all;
}
void init_sys ()
{
XBYTE[0x8000] = 0xff;
XBYTE[0xa000] = 0x00;
state_SMG_all ( 0xff );
}
void write_at24c02 ( unsigned char addr_write , unsigned char value_write )
{
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(addr_write);
I2CWaitAck();
I2CSendByte(value_write);
I2CWaitAck();
I2CStop();
}
/**
void write_at24c02a ( unsigned char addr_write , unsigned char value_write )
{
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(addr_write);
I2CWaitAck();
I2CSendByte(value_write);
I2CWaitAck();
I2CStop();
}
unsigned char read_at24c02 ( unsigned char addr_read )
{
unsigned char power_count_temp;
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(addr_read);
I2CWaitAck();
I2CStart();
I2CSendByte(0xa1);
I2CWaitAck();
power_count_temp = I2CReceiveByte();
I2CSendAck(1);
I2CStop();
return power_count_temp;
}
*/
unsigned char rb2_value = 0;
void rb2running()
{
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(0x03);
I2CWaitAck();
I2CStop();
I2CStart();
I2CSendByte(0x91);
I2CWaitAck();
rb2_value = I2CReceiveByte();
I2CSendAck(1);
I2CStop();
}
void init_timer0 (void) //50微秒@11.0592MHz,定时器0
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x02; //设置定时器模式
TL0 = 0xD2; //设置定时初值
TH0 = 0xD2; //设置定时重载值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
EA = 1;
ET0 = 1;
}
void init_timer1(void) //50毫秒@11.0592MHz,定时器1
{
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x10; //设置定时器模式
TL1 = 0x00; //设置定时初值
TH1 = 0x4C; //设置定时初值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
EA = 1;
ET1 = 1;
}
bit SMG_flag = 0;
unsigned char flash_count = 0;
void timer0_service () interrupt 1
{
TL0 = 0x98; //设置定时初值
TH0 = 0xF1; //设置定时初值
if ( sys_stop == 0 )
{
return ;
}
if ( ++pwm_50us == 100 )
{
pwm_50us = 0;
}
if ( pwm_50us % 20 == 0 )
{
if ( SMG_flag == 0 )
{
if ( ++flash_count == 7 )
{
flash_count = 0;
}
}
else if ( SMG_flag == 1 )
{
if ( ++flash_count > 1 )
{
flash_count = 0;
}
}
SMG_flashing ();
}
if ( pwm_50us < pwm_duty )
{
XBYTE[0x8000] = value_led;
}
else
{
XBYTE[0x8000] = 0xff;
}
}
unsigned char led_move = 0;
unsigned char set_time = 4; //设定的流转时间,取值4~12
unsigned char led_bit = 0; //设定led的对应位
unsigned char count_50ms = 0;
unsigned char count_100ms = 0;
bit if_800ms = 0;
void timer1_service () interrupt 3
{
TL1 = 0x00; //设置定时初值
TH1 = 0x4C; //设置定时初值
count_50ms ++;
if ( count_50ms % 2 == 0 )
{
if ( ++count_100ms >= set_time )
{
if ( led_stop == 0 )
{
led_move ++;
}
count_100ms = 0;
}
rb2running ();
}
if ( count_50ms == 16 )
{
count_50ms = 0;
save_data(); //将数据写入at24c02存储起来
if_800ms = ~if_800ms;
}
}
bit set_flag = 0;
unsigned char led_mode_value = 0;
void valuerunning ()
{
if ( set_flag == 0 )
{
if ( rb2_value < 53 )
{
pwm_duty = 5;
led_mode_value = 1;
}
else if ( rb2_value < 106 )
{
pwm_duty = 35;
led_mode_value = 2;
}
else if ( rb2_value < 159 )
{
pwm_duty = 65;
led_mode_value = 3;
}
else if ( rb2_value < 255 )
{
pwm_duty = 95;
led_mode_value = 4;
}
}
else if ( set_flag == 1 )
{
if ( led_mode_value == 1 )
{
pwm_duty = 5;
}
else if ( led_mode_value == 2 )
{
pwm_duty = 35;
}
else if ( led_mode_value == 3 )
{
pwm_duty = 65;
}
else if ( led_mode_value == 4 )
{
pwm_duty = 95;
}
}
if ( key6_state != 0 )
{
set_flag = 1;
}
else
{
set_flag = 0;
}
if ( led_move < 8 )
{
value_led = ledmode1[led_move];
}
else if ( led_move < 16 )
{
value_led = ledmode2[led_move-8];
}
else if ( led_move < 20 )
{
value_led = ledmode3[led_move-16];
}
else if ( led_move < 24 )
{
value_led = ledmode4[led_move-20];
}
else
{
led_move = 0;
}
if ( key6_state == 1 && key5_state == 1 )
{
key5_state = 0;
if ( ++led_mode_value == 5 )
{
led_mode_value = 4;
}
}
else if ( key6_state == 1 && key4_state == 1 )
{
key4_state = 0;
if ( --led_mode_value == 255 )
{
led_mode_value = 0;
}
}
else if ( key6_state == 2 && key4_state == 1 )
{
key4_state = 0;
if ( --set_time == 255 )
{
set_time = 4;
}
}
else if ( key6_state == 2 && key5_state == 1 )
{
key5_state = 0;
if ( ++set_time == 13 )
{
set_time = 12;
}
}
}
void SMG_flashing ()
{
state_SMG_all ( 0xff );
if ( SMG_flag == 0 )
{
if ( key6_state == 0 )
{
state_SMG_all ( 0xff );
}
else
{
switch ( flash_count )
{
case 0:
state_SMG ( 0 , duanma[16] );
break;
case 1:
if ( key6_state == 1 && if_800ms == 0 )
{
state_SMG ( 1 , 0xff );
}
else
{
state_SMG ( 1 , duanma[led_mode_value] );
}
break;
case 2:
state_SMG ( 2 , duanma[16] );
break;
case 3:
if ( key6_state == 2 && if_800ms == 0 )
{
state_SMG ( 5 , 0xff );
}
else
{
if ( set_time > 9 )
{
state_SMG ( 4 , duanma[1] );
}
}
break;
case 4:
if ( key6_state == 2 && if_800ms == 0 )
{
state_SMG ( 5 , 0xff );
}
else
{
state_SMG ( 5 , duanma[set_time%10] );
}
break;
case 5:
if ( key6_state == 2 && if_800ms == 0 )
{
state_SMG ( 6 , 0xff );
}
else
{
state_SMG ( 6 , duanma[0] );
}
break;
case 6:
if ( key6_state == 2 && if_800ms == 0 )
{
state_SMG ( 7 , 0xff );
}
else
{
state_SMG ( 7 , duanma[0] );
}
break;
}
}
}
else if ( SMG_flag == 1 && key6_state == 0 )
{
switch ( flash_count )
{
case 0 :
state_SMG ( 6 , duanma[led_mode_value/10] );
break;
case 1 :
state_SMG ( 7 , duanma[led_mode_value%10] );
break;
}
}
}
void Delay2ms() //@11.0592MHz
{
unsigned char i, j;
_nop_();
_nop_();
i = 22;
j = 128;
do
{
while (--j);
} while (--i);
}
void keyrunning ()
{
if ( S7 == 0 )
{
Delay2ms();
if ( S7 == 0 )
{
while ( S7 == 0 );
led_stop = ~led_stop;
sys_stop = 1;
}
}
else if ( S6 == 0 )
{
Delay2ms();
if ( S6 == 0 )
{
while ( S6 == 0 );
if ( ++key6_state == 3 )
{
key6_state = 0;
}
}
}
else if ( S5 == 0 )
{
Delay2ms();
if ( S5 == 0 )
{
while ( S5 == 0 );
if ( key6_state != 0 )
{
key5_state = ~key5_state;
}
}
}
else if ( S4 == 0 )
{
Delay2ms ();
if ( S4 == 0 )
{
while ( S4 == 0 )
{
SMG_flag = 1;
}
SMG_flag = 0;
if ( key6_state != 0 )
{
key4_state = ~key4_state;
}
}
}
}
/**功能要求中,没有提到要实现写入内存存储的功能。但是硬件图里花了外部存储器,因此我还是把代码写出来了
//针对小蜜蜂老师提到的内存中原有数据会影响读取数据,这里的逻辑应该可以规避该错误
unsigned char sys_count = 1; //开机次数记录
void init_at24c02 ()
{
unsigned char tmp_mode = 0;
unsigned char tmp_time = 0;
tmp_mode = read_at24c02 ( 0x02 );
tmp_time = read_at24c02 ( 0x03 );
if ( tmp_mode > 4 && tmp_time > 12 ) //判断是不是第一次开机,如果内存中没有有效数据,则为第一次开机
{
write_at24c02a ( 0x01 , sys_count );
}
sys_count = read_at24c02 ( 0x01 );
sys_count ++;
}
*/
void save_data()
{
// write_at24c02 ( 0x01 , sys_count );
write_at24c02 ( 0x02 , led_mode_value );
write_at24c02 ( 0x03 , set_time );
}
void main ()
{
init_sys();
init_timer1 ();
init_timer0 ();
// init_at24c02 ();
while ( 1 )
{
valuerunning ();
keyrunning();
}
}
/**
该代码为蓝桥杯单片机组第九届省赛程序
作者:archie474:CSDN
欢迎在博客中留言代码中的问题,以及存在的疑惑
*/