这是一个不知道来源的模拟题目,没有完全完成,只作代码记录,不作分析和展示,极其冗长,但里面有长按短按双击的复合,可以看看。
目录
- 题目
- 代码
- 底层驱动
- 主程序核心代码
- 关键:双击单击长按复合代码
题目
代码
底层驱动
IIC(EEPROM没在主程序用)
unsigned char guangmin(){
unsigned char ret;
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(0x41);
I2CWaitAck();
I2CStart();
I2CSendByte(0x91);
I2CWaitAck();
ret = I2CReceiveByte();
I2CSendAck(1);
I2CStop();
return ret;
}
void DAC(unsigned char dat){
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(0x41);
I2CWaitAck();
I2CSendByte(dat);
I2CWaitAck();
I2CStop();
}
void eepromwirte(unsigned char addr,unsigned char dat){
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CSendByte(dat);
I2CWaitAck();
I2CStop();
}
unsigned char eepromread(unsigned char addr){
unsigned char ret;
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(addr);
I2CWaitAck();
I2CStart();
I2CSendByte(0xa1);
I2CWaitAck();
ret = I2CReceiveByte();
I2CSendAck(1);
I2CStop();
return ret;
}
主程序核心代码
#include <STC15F2K60S2.H>
#include "intrins.h"
#include "inithc138.h"
#include "delay.h"
#include "onewire.h"
#include "iic.h"
#include "ds1302.h"
#define de 5
code unsigned char Seg_Table[17] =
{
0xc0, //0
0xf9, //1
0xa4, //2
0xb0, //3
0x99, //4
0x92, //5
0x82, //6
0xf8, //7
0x80, //8
0x90, //9
0x88, //A
0x83, //b
0xc6, //C
0xa1, //d
0x86, //E
0x8e, //F
0xbf
};
unsigned char show = 0;//显示功能切换
unsigned char canshu = 0;//参数界面切换
bit mode = 1;//控制模式切换
unsigned char jiaozhun = 0;//校准设置切换
bit huixian = 0;//回显模式切换
unsigned int temp = 0;//温度
bit ce = 1;
unsigned int time = 0;//超声波传播时间
long distance = 0;//距离
unsigned char cejushangxian = 80;//测距上限
unsigned char cejuxiaxian = 20;//测距下限
unsigned int tempcan = 30;//温度参数
unsigned char light = 0;//光敏参数
unsigned char ds1302writeaddr[3] = {0x80,0x82,0x84};
unsigned char ds1302readaddr[3] = {0x81,0x83,0x85};
unsigned char rtctime[3] = {0x05,0x29,0x10};
char disjiao = 0;//距离校准值
int tempjiao = 0;//温度校准值
unsigned char temptime[3] = {0};//温度超限时间
unsigned char distime[3] = {0};//温度超限时间
double daczhi = 0;//DAC输出大小
bit zhouqi = 0;//1为进入按键周期
unsigned char keycount = 0;//按键周期计时
unsigned char cishu = 0;
bit zhouqi1 = 0;//1为进入按键周期
unsigned char keycount1 = 0;//按键周期计时
unsigned char cishu1 = 0;
bit keystat = 0;//按键状态(长短按)
unsigned int count = 0;//长按计时
unsigned char ledstat = 0xff;
unsigned char ledcount = 0;
bit ledflag = 0;
bit chaoxian = 0;
unsigned int tempshow = 0;//校准后的温度
//*****************************************测温模块
void cewen(){
unsigned char LSB,MSB;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
if(ce){
Delay(520);
}
ce = 0;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
LSB = Read_DS18B20();
MSB = Read_DS18B20();
init_ds18b20();
temp = ((MSB << 8) | LSB) * 0.625;
tempshow = temp + tempjiao;
}
//*****************************************
//*****************************************超声波模块
sbit TX = P1^0;
sbit RX = P1^1;
void showselect();
void Delay13us(void) //@12.000MHz
{
unsigned char data i;
_nop_();
_nop_();
i = 36;
while (--i);
}
void fangbo(){
unsigned char i;
for(i = 0;i < 8;i++){
TX = 1;
Delay13us();
TX = 0;
Delay13us();
}
}
void initpca(){
CMOD = 0x01;
CCON = 0x00;
}
void ceju(){
CH = 0x00;
CL = 0x00;
CF = 0;
CR = 0;
fangbo();
CR = 1;
while((RX == 1) && (CH < 0x17));
CR = 0;
if(RX == 0){
RX = 1;
time = (CH << 8) | CL;
distance = time * 0.017;
}
}
//*****************************************
//*****************************************DS1302实时时钟
void ds1302config(){
unsigned char i;
Write_Ds1302_Byte(0x8e,0x00);
for(i = 0;i < 3;i++){
Write_Ds1302_Byte(ds1302writeaddr[i],rtctime[i]);
}
Write_Ds1302_Byte(0x8e,0x80);
}
void ds1302read(){
unsigned char i;
for(i = 0;i < 3;i++){
rtctime[i] = Read_Ds1302_Byte(ds1302readaddr[i]);
}
}
//*****************************************
//*****************************************显示功能
void shujujiemian(){//数据界面
showsmg(1,Seg_Table[12]);
showsmg(2,Seg_Table[tempshow / 100]);
showsmg(3,Seg_Table[tempshow / 10 % 10] & 0x7f);
showsmg(4,Seg_Table[tempshow % 10]);
if((distance + disjiao) >= 0){
showsmg(8,Seg_Table[(distance + disjiao) % 10]);
if((distance + disjiao) > 9){
showsmg(7,Seg_Table[(distance + disjiao) / 10 % 10]);
}
}else{
showsmg(7,0xc7);
showsmg(8,0xc7);
}
}
void p1(){//参数P1
showsmg(1,0x8c);
showsmg(2,Seg_Table[1]);
showsmg(6,0x89);
showsmg(7,Seg_Table[cejushangxian / 10]);
showsmg(8,Seg_Table[cejushangxian % 10]);
}
void p2(){//参数P2
showsmg(1,0x8c);
showsmg(2,Seg_Table[2]);
showsmg(6,0xc7);
showsmg(7,Seg_Table[cejuxiaxian / 10]);
showsmg(8,Seg_Table[cejuxiaxian % 10]);
}
void p3(){//参数P3
showsmg(1,0x8c);
showsmg(2,Seg_Table[3]);
showsmg(7,Seg_Table[tempcan / 10]);
showsmg(8,Seg_Table[tempcan % 10]);
}
void p4(){//参数P4
showsmg(1,0x8c);
showsmg(2,Seg_Table[4]);
if(mode){
showsmg(4,0x8c);
showsmg(5,Seg_Table[14]);
}else{
showsmg(4,Seg_Table[10]);
showsmg(5,0xc1);
}
showsmg(8,Seg_Table[light % 10]);
if(light > 9){
showsmg(7,Seg_Table[light / 10 % 10]);
}
if(light > 99){
showsmg(6,Seg_Table[light / 100 % 10]);
}
}
void canshujiemian(){//参数界面
switch(canshu){
case 0:p1();break;
case 1:p2();break;
case 2:p3();break;
case 3:p4();break;
}
}
void shijianjiemian(){//时间显示
showsmg(1,Seg_Table[rtctime[2] / 16]);
showsmg(2,Seg_Table[rtctime[2] % 16]);
showsmg(3,Seg_Table[16]);
showsmg(4,Seg_Table[rtctime[1] / 16]);
showsmg(5,Seg_Table[rtctime[1] % 16]);
showsmg(6,Seg_Table[16]);
showsmg(7,Seg_Table[rtctime[0] / 16]);
showsmg(8,Seg_Table[rtctime[0] % 16]);
}
void f1(){
showsmg(1,Seg_Table[15]);
showsmg(2,Seg_Table[1]);
if(disjiao >= 0){
showsmg(8,Seg_Table[disjiao % 10]);
if(disjiao > 9){
showsmg(7,Seg_Table[disjiao / 10 % 10]);
}
}else if(disjiao < 0){
if(disjiao >= -9){
showsmg(8,Seg_Table[-(disjiao) % 10]);
showsmg(7,Seg_Table[16]);
}
if(disjiao < -9){
showsmg(8,Seg_Table[-(disjiao) % 10]);
showsmg(7,Seg_Table[-(disjiao) / 10 % 10]);
showsmg(6,Seg_Table[16]);
}
}
}
void f2(){
showsmg(1,Seg_Table[15]);
showsmg(2,Seg_Table[2]);
if(tempjiao > 0){
showsmg(8,Seg_Table[tempjiao % 10]);
showsmg(7,Seg_Table[tempjiao / 10 % 10] & 0x7f);
}else if(tempjiao < 0){
showsmg(8,Seg_Table[(-tempjiao) % 10]);
showsmg(7,Seg_Table[(-tempjiao) / 10 % 10] & 0x7f);
showsmg(6,Seg_Table[16]);
}else if(tempjiao == 0){
showsmg(8,Seg_Table[0]);
}
}
void f3(){
showsmg(1,Seg_Table[15]);
showsmg(2,Seg_Table[3]);
if(mode){
showsmg(7,0x8c);
showsmg(8,Seg_Table[14]);
}else{
showsmg(7,Seg_Table[10]);
showsmg(8,0xc1);
}
}
void jiaozhunshezhi(){//校准设置界面
switch(jiaozhun){
case 0:f1();break;
case 1:f2();break;
case 2:f3();break;
}
}
void wenduchaoxian(){//温度超限时间记录
showsmg(1,0x8b);
showsmg(2,0xa7);
if(temptime[2] != 0){
showsmg(3,Seg_Table[temptime[2] / 16]);
showsmg(4,Seg_Table[temptime[2] % 16]);
showsmg(5,Seg_Table[temptime[1] / 16]);
showsmg(6,Seg_Table[temptime[1] % 16]);
showsmg(7,Seg_Table[temptime[0] / 16]);
showsmg(8,Seg_Table[temptime[0] % 16]);
}
}
void julichaoxian(){//距离超限时间记录
showsmg(1,0x8b);
showsmg(2,0xa1);
if(distime[2] != 0){
showsmg(3,Seg_Table[distime[2] / 16]);
showsmg(4,Seg_Table[distime[2] % 16]);
showsmg(5,Seg_Table[distime[1] / 16]);
showsmg(6,Seg_Table[distime[1] % 16]);
showsmg(7,Seg_Table[distime[0] / 16]);
showsmg(8,Seg_Table[distime[0] % 16]);
}
}
void huixianmoshi(){//回显模式
if(huixian == 0){
wenduchaoxian();
}else{
julichaoxian();
}
}
//*****************************************
//*****************************************DAC输出
void DACshuchu(){
if((disjiao + distance) <= cejuxiaxian){
daczhi = 51;
}else if((disjiao + distance) >= cejushangxian){
daczhi = 255;
}else{
daczhi = (204 / (cejushangxian - cejuxiaxian)) * (disjiao + distance - cejuxiaxian) + 51;
}
DAC(daczhi);
}
//*****************************************
//*****************************************
void showselect(){
switch(show){
case 0:shujujiemian();break;
case 1:canshujiemian();break;
case 2:shijianjiemian();break;
case 3:jiaozhunshezhi();break;
case 4:huixianmoshi();break;
}
}
//*****************************************
//*****************************************单击双击检测
void Timer0_Isr(void) interrupt 1
{
ledcount++;
if(zhouqi){
keycount++;
}
if(keycount == 100){
zhouqi = 0;
}
if(zhouqi1){
keycount1++;
}
if(keycount1 == 100){
zhouqi1 = 0;
}
if(keystat){
count++;
}
if(ledcount == 200){
ledcount = 0;
}
if(ledcount % 20 == 0){
ledflag = ~ledflag;
}
}
void Timer0_Init(void) //5毫秒@12.000MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xA0; //设置定时初始值
TH0 = 0x15; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
EA = 1;
}
//*****************************************
//*****************************************按键扫描
void scankey(){
P33 = 0;P32 = 1;P44 = 1;P35 = 1;
if(P44 == 0){//S4
Delay(de);while(P44 == 0){showselect();}
show++;jiaozhun = 0;canshu = 0;huixian = 0;
show %= 5;
}
if(P35 == 0){//S12
Delay(de);if(P35 == 0){zhouqi = 1;}while(P35 == 0){showselect();}
cishu++;
if(show == 1){
if(canshu == 2){
tempcan++;
if(tempcan > 40){tempcan = 40;}
}else if((canshu == 3) && (mode == 1)){
light += 10;
if(light > 200){light = 200;}
}
}
if(show == 3){
if(jiaozhun == 0){
disjiao++;
if(disjiao > 10){disjiao = 10;}
}else if(jiaozhun == 1){
tempjiao++;
if(tempjiao > 30){tempjiao = 30;}
}
}
}
if(show == 1){
if(zhouqi == 0){
if(cishu == 1){//单击
if(show == 1){
if(canshu == 0){
cejushangxian++;
if(cejushangxian > 90){cejushangxian = 90;}
}else if(canshu == 1){
cejuxiaxian++;
if(cejuxiaxian > (cejushangxian - 20)){cejuxiaxian = cejushangxian - 20;}
}
}
}
if(cishu == 2){//双击
if(show == 1){
if(canshu == 0){
cejushangxian += 10;
if(cejushangxian > 90){cejushangxian = 90;}
}else if(canshu == 1){
cejuxiaxian += 10;
if(cejuxiaxian > (cejushangxian - 20)){cejuxiaxian = cejushangxian - 20;}
}
}
}
keycount = 0;
cishu = 0;
}
}
P33 = 1;P32 = 0;P44 = 1;P35 = 1;
if(P44 == 0){//S5
Delay(de);while(P44 == 0){showselect();}
if(show == 1){canshu++;canshu %= 4;}
if(show == 3){jiaozhun++;jiaozhun %= 3;}
if(show == 4){huixian = ~huixian;}
}
if(P35 == 0){//S13
Delay(de);if(P35 == 0){zhouqi1 = 1;}while(P35 == 0){keystat = 1;showselect();}
keystat = 0;
if(count < 400){//短按
cishu1++;
if(show == 1){
if(canshu == 2){
tempcan--;
if(tempcan < 20){tempcan = 20;}
}else if((canshu == 3) && (mode == 1)){
light -= 10;
if(light > 200){light = 0;}
}
}
if(show == 3){
if(jiaozhun == 0){
disjiao--;
if(disjiao < -10){disjiao = -10;}
}else if(jiaozhun == 1){
tempjiao--;
if(tempjiao < -30){tempjiao = -30;}
}
}
}else{
if(show == 3){
if(jiaozhun == 0){disjiao = 0;}
if(jiaozhun == 1){tempjiao = 0;}
}
}
count = 0;
}
if(show == 1){
if(zhouqi1 == 0){
if(cishu1 == 1){//单击
if(show == 1){
if(canshu == 0){
cejushangxian--;
if(cejushangxian < (cejuxiaxian + 20)){cejushangxian = cejuxiaxian + 20;}
}else if(canshu == 1){
cejuxiaxian--;
if(cejuxiaxian < 10){cejuxiaxian = 10;}
}
}
}
if(cishu1 == 2){//双击
if(show == 1){
if(canshu == 0){
cejushangxian -= 10;
if(cejushangxian < (cejuxiaxian + 20)){cejushangxian = (cejuxiaxian + 20);}
}else if(canshu == 1){
cejuxiaxian -= 10;
if(cejuxiaxian < 10){cejuxiaxian = 10;}
}
}
}
keycount1 = 0;
cishu1 = 0;
}
}
}
//*****************************************
//*****************************************LED模块与超限判断
void chaoxianpanduan(){
if(((temp + tempjiao) / 10) > tempcan){
chaoxian = 1;
temptime[0] = rtctime[0];
temptime[1] = rtctime[1];
temptime[2] = rtctime[2];
//eepromwirte()
}
}
void led(){
unsigned char tmp = 0;
if(tempshow > tempcan * 10){
ledstat = ledstat & ~0x10;
}else{
ledstat = ledstat | 0x10;
}
if((show == 0) && (ledflag == 1)){
ledstat = ledstat & ~0x01;
}else{
ledstat = ledstat | 0x01;
}
if((show == 3) && (ledflag == 1)){
ledstat = ledstat & ~0x02;
}else{
ledstat = ledstat | 0x02;
}
if(((distance + disjiao) <=cejushangxian) && ((distance + disjiao) >= cejuxiaxian)){
ledstat = ledstat | 0x08;
}else{
ledstat = ledstat & ~0x08;
}
tmp = guangmin();
if((mode == 1) && (tmp > light)){
ledstat = ledstat & ~0x80;
}else{
ledstat = ledstat | 0x80;
}
outputp0(4,ledstat);
}
//*****************************************
void main(){
ds1302config();
cewen();
initpca();
initsys();
ceju();
Timer0_Init();
while(1){
if(mode == 0){
light = guangmin();
}
cewen();
led();
ceju();
showselect();
ds1302read();
DACshuchu();
scankey();
chaoxianpanduan();
}
}
关键:双击单击长按复合代码
以S12为例
//*****************************************单击双击检测
void Timer0_Isr(void) interrupt 1
{
ledcount++;
if(zhouqi){
keycount++;
}
if(keycount == 100){
zhouqi = 0;
}
if(zhouqi1){
keycount1++;
}
if(keycount1 == 100){
zhouqi1 = 0;
}
if(keystat){
count++;
}
if(ledcount == 200){
ledcount = 0;
}
if(ledcount % 20 == 0){
ledflag = ~ledflag;
}
}
void Timer0_Init(void) //5毫秒@12.000MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xA0; //设置定时初始值
TH0 = 0x15; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
EA = 1;
}
//*****************************************
P33 = 0;P32 = 1;P44 = 1;P35 = 1;
if(P44 == 0){//S4
Delay(de);while(P44 == 0){showselect();}
show++;jiaozhun = 0;canshu = 0;huixian = 0;
show %= 5;
}
if(P35 == 0){//S12
Delay(de);if(P35 == 0){zhouqi = 1;}while(P35 == 0){showselect();}
cishu++;
if(show == 1){
if(canshu == 2){
tempcan++;
if(tempcan > 40){tempcan = 40;}
}else if((canshu == 3) && (mode == 1)){
light += 10;
if(light > 200){light = 200;}
}
}
if(show == 3){
if(jiaozhun == 0){
disjiao++;
if(disjiao > 10){disjiao = 10;}
}else if(jiaozhun == 1){
tempjiao++;
if(tempjiao > 30){tempjiao = 30;}
}
}
}
if(show == 1){
if(zhouqi == 0){
if(cishu == 1){//单击
if(show == 1){
if(canshu == 0){
cejushangxian++;
if(cejushangxian > 90){cejushangxian = 90;}
}else if(canshu == 1){
cejuxiaxian++;
if(cejuxiaxian > (cejushangxian - 20)){cejuxiaxian = cejushangxian - 20;}
}
}
}
if(cishu == 2){//双击
if(show == 1){
if(canshu == 0){
cejushangxian += 10;
if(cejushangxian > 90){cejushangxian = 90;}
}else if(canshu == 1){
cejuxiaxian += 10;
if(cejuxiaxian > (cejushangxian - 20)){cejuxiaxian = cejushangxian - 20;}
}
}
}
keycount = 0;
cishu = 0;
}
}
注意几个要点:
1、涉及到双击,要把判断部分抽离按键按下阶段,否则不会进行判断
2、注意按键周期,在编程过程中可以用数码管显示按键周期和按键按下进行调试。
3、定时器尽量使用1T,优先级尽量高。