基础不是很好,所以程序思路只能说够用就行,之后我会慢慢修改回来完善。
今晚跟人吵架了很难受QWQ
1.LED
上一节已经分析过,先操作锁存器P2口,再操作P0口。不过这块板子有些缺陷,要初始化把继电器关了,再把LED关了。偷懒的话把LED初始化放在后面,这样锁存器依然是选中LED的,就可以直接进行LED的操作。(12MHZ)
#include //流水灯程序
typedef unsigned long u32;
typedef unsigned int uint; //对数据类型进行声明定义
typedef unsigned char uchar;
//N ms延时
void delay_ms(uint n)
{
uint i,j;
for (i = n; i>0;i--)
for (j = 114;j>0;j--);
}
void main(void)
{
uchar i = 0;
P2 = 0XA0,P0 = 0X00;//关闭继电器
P2 = 0X80;P0 = 0XFF;//关LED
while(1)
{
for( i = 0;i <8;i++)
{
P0 = ~(1<<i);
delay_ms(1000);
}
}
}
2.独立按键
按键之前我研究了很多种办法,比如什么状态标志位判断或者说是三行代码得到TRG。然后经过这么久的洗刷还是觉得比赛就用最简单的消抖按键就行了(毕竟按键也不多,复制粘贴也比较轻松)这个唯一的毛病就是需要占用定时器0(专门拿一个定时器来给按键)。后期如果遇到简单好使的方就补充。(长短按键,如果是一般的,用swich也可以做)
/*长按一个灯亮,短按另一个灯亮*/
#include
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned long uint32;
sbit key1 = P3^0;
uint key_count;
uchar key_state;
uchar flag_key =0;
void Timer0Init(void);
void delay_ms(uint n)
{
uint i,j;
for (i = n; i>0;i--)
for (j = 114;j>0;j--);
}
void Key1_scan(void)
{
if (!key1)
{
delay_ms(10);
if (!key1)
{
TR0 = 1;
while(!key1);
if (flag_key)
{
key_state = 1;
flag_key = 0;
}
else
{
key_state = 2;
}
}
}
}
void main(void)
{
uchar i = 0;
P2 = 0XA0,P0 = 0X00;//关闭继电器
P2 = 0X80;P0 = 0XFF;//关LED
Timer0Init();
while(1)
{
Key1_scan();
switch(key_state)
{
case 1:P0 = 0xFe;break;
case 2:P0 = 0Xf7;break;
}
}
}
void Timer0Init(void) //5毫秒@11.0592MHz
{
EA = 1;
ET0 = 1;
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x00; //设置定时初值
TH0 = 0x28; //设置定时初值
TF0 = 0; //清除TF0标志
}
void Timer0() interrupt 1
{
key_count++;
if (key_count = 500)
{
flag_key = 1;
key_count = 0;
TR0 = 0;
}
}
3.矩阵按键
跳线帽拔到BTN端。很容易得出这个矩阵按键就是X-Y格式排列的。所以定位行列就可以定位到对应的按键。
C语言中要用到的 switch语句
switch(表达式)
{
case(常量表达式1): 语句1; break;
case(常量表达式2): 语句2; break;
case(常量表达式3): 语句3; break;
case(常量表达式4): 语句4; break;
default:break;//默认..可以省略
}
程序思路:
先检测是否有按键按下,再判断按键的位置。(用于都是一个口上)
void jzKey(void)
{
if (P3 != 0xFF)
{
Delay10ms();
if(P3 != 0xFF)
{
P3 = 0X0F;//给KEY初值,先检测行
switch(P3)//先检测行
{
case(0x0e): KeyValue=1;break;
case(0x0d): KeyValue=2;break;
case(0x0b): KeyValue=3;break;
case(0x07): KeyValue=4;break;
}
P3 = 0XF0;//测试列
switch(P3)
{
case(0xe0): KeyValue=KeyValue+12;break;
case(0xd0): KeyValue=KeyValue+8;break;
case(0xb0): KeyValue=KeyValue+4;break;
case(0x70): KeyValue=KeyValue;break;
}
while(!P3); //检测按键松手检测
}
}
}
发现自己犯了个错,蓝桥杯的板子上的转接口把口的位置变了。
所以按照某位大可爱给的CTRLCV办法,干脆就直接sbit了。
/*代码片段:先判断一行一行的判断*/
sbit H1 = P3^0;
sbit H2 = P3^1;
sbit H3 = P3^2;
sbit H4 = P3^3;
sbit L1 = P4^4;//P3^7 = P4^4
sbit L2 = P4^2;//P3^6 = P4^2
sbit L3 = P3^5;
sbit L4 = P3^4;
uchar jzKey(void)
{
static uchar key_value = 0;
H1 = 0;
H2 = H3 = H4 = L1 =L2 =L3 =L4 =1;
if(!L1)
{
Delay10ms();
if(!L1)
{
key_value = 1;
}while(!L1);
}
else if(!L2)//复制修改
{
Delay10ms();
if(!L2)
{
key_value = 2;
}while(!L2);
}
else if(!L3)
{
Delay10ms();
if(!L3)
{
key_value = 3;
}while(!L3);
}
else if(!L4)
{
Delay10ms();
if(!L4)
{
key_value = 4;
}while(!L4);
}
//复制修改
H2 = 0;
H1 = H3 = H4 = L1 =L2 =L3 =L4 =1;
if(!L1)
{
Delay10ms();
if(!L1)
{
key_value = 5;
}while(!L1);
}
else if(!L2)
{
Delay10ms();
if(!L2)
{
key_value = 6;
}while(!L2);
}
else if(!L3)
{
Delay10ms();
if(!L3)
{
key_value = 7;
}while(!L3);
}
else if(!L4)
{
Delay10ms();
if(!L4)
{
key_value = 8;
}while(!L4);
}
H3 = 0;
H2 = H3 = H4 = L1 =L2 =L3 =L4 =1;
if(!L1)
{
Delay10ms();
if(!L1)
{
key_value = 9;
}while(!L1);
}
else if(!L2)
{
Delay10ms();
if(!L2)
{
key_value = 10;
}while(!L2);
}
else if(!L3)
{
Delay10ms();
if(!L3)
{
key_value = 11;
}while(!L3);
}
else if(!L4)
{
Delay10ms();
if(!L4)
{
key_value = 12;
}while(!L4);
}
H4 = 0;
H2 = H3 = H1 = L1 =L2 =L3 =L4 =1;
if(!L1)
{
Delay10ms();
if(!L1)
{
key_value = 13;
}while(!L1);
}
else if(!L2)
{
Delay10ms();
if(!L2)
{
key_value = 14;
}while(!L2);
}
else if(!L3)
{
Delay10ms();
if(!L3)
{
key_value = 15;
}while(!L3);
}
else if(!L4)
{
Delay10ms();
if(!L4)
{
key_value = 16;
}while(!L4);
}
return key_value;
}
void main()
{
uchar key = 0;
All_Init();
while(1)
{
key = jzKey();
if(key == 6)
{
P2 = (P2 & 0X1F | 0X80);
P0 = 0X00;
key = 0;
}
}
}
数码管一般考察都是动态,先位选再段选;
https://blog.csdn.net/zlllg/article/details/82119338可以参考一下这个老哥的博客,先码着明天看~
//数码管动态扫描核心代码
code unsigned char Duan_Data[] = {
0Xc0,0xf9,0xa4,0xb0,0X99,0X92,0X82,0XF8,0X80,0X90,0x88,0x83,0xc6,0xa1,0x86,0x8e}; //共阳的段码,会给的不用记
code unsigned char Wei_Data[] = {
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};//要记住的
void Display(int dat)
{
uchar i,j = 0;
uchar str[3];
str[0] = dat%10;//个位
str[1] = dat/10%10;//十位
str[2] = dat/100;//百位
for(i = 0; i<3;i++)//要显示几位就循几次
{
P2 = (P2&0X1F|0XC0);//位
P0 = Wei_Data[7-i];
P2= (P2&0X1F|0XE0);//段
P0 = Duan_Data[str[i]];
Delay_ms(3);//反复试了几次,比较稳定的延时
P0 = 0XFF;//消影
}
}
void main(void)
{
All_Init();
while(1)
{
Display(321);
}
}
当要求加小数点的时候,我们知道共阳段选小数点是0X7F ,对特定位清零用&,所以只需要再加上 P0 = Duan_Data[str[i]]&0X7F。
P2 = (P2&0X1F|0XA0);
P0 = 0X10|0X40;//继电器/蜂鸣器开