前言:第三套模拟题,说是国赛其实就是省赛难度,而且出题不规范,导致我一些理解上的错误,但是题目中有一些值得练习的点。
题目
个人理解和分析
这是4T官网出的第三套题,也不知道是哪年省赛题的改编,在旋钮时的表述不知道S8按一下在干什么,我就理解成了要按住S8才能扭,就导致我三个点扣了分。
当然后续刷分可以刷到满分,但是多次提交会判定请求过多,当我写下这篇博文的时候已经时凌晨,便也等不得。相反,我觉得按住再扭旋钮可以作为一个较为新颖的考点。
其他的话甚至没有比今年省赛复杂。我便不展示演示视频了。
底层驱动代码
IIC
unsigned char RB2(){
unsigned char ret;
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(0x43);
I2CWaitAck();
I2CStart();
I2CSendByte(0x91);
I2CWaitAck();
ret = I2CReceiveByte();
I2CSendAck(1);
I2CStop();
return ret;
}
锁存器和延时
void Delay(unsigned char xms) //@12.000MHz
{
while(xms--){
unsigned char data i, j;
i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}
}
#include <STC12C5A60S2.H>
#include "delay.h"
void inithc138(unsigned char channel){
switch(channel){
case 0:P2 = (P2 & 0x1f) | 0x00;break;
case 4:P2 = (P2 & 0x1f) | 0x80;break;
case 5:P2 = (P2 & 0x1f) | 0xa0;break;
case 6:P2 = (P2 & 0x1f) | 0xc0;break;
case 7:P2 = (P2 & 0x1f) | 0xe0;break;
}
}
void outputp0(unsigned char channel,unsigned char dat){
inithc138(0);
P0 = dat;
inithc138(channel);
inithc138(0);
}
void showsmg(unsigned char pos,unsigned char dat){
outputp0(7,0xff);
outputp0(6,0x01 << (pos - 1));
outputp0(7,dat);
Delay(1);
}
void initsys(){
outputp0(4,0xff);
outputp0(5,0x00);
outputp0(6,0xff);
outputp0(7,0xff);
}
主程序核心代码
注:我没有修改按住才能扭动的功能,代码不难理解,自行修改即可
#include <STC12C5A60S2.H>
#include "intrins.h"
#include "delay.h"
#include "inithc138.h"
#include "iic.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 int time = 0;//传播时间
unsigned int distance = 0;//传播距离
bit canshu = 0;//切换旋钮模式和按钮模式
unsigned char canshuxiaxian = 10;//参数下限
unsigned char canshushangxian = 60;//参数上限
unsigned char baojingcishu = 0;//报警次数
unsigned char voltage = 0;
unsigned char ledstat = 0xff;
bit flag = 1;
unsigned char count = 0;
bit flag2 = 0;
//************************************超声波
sbit TX = P1^0;
sbit RX = P1^1;
void initpca(){
CMOD = 0x01;
CCON = 0x00;
}
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 ceju(){
CL = 0x00; //设置定时初始值
CH = 0x00; //设置定时初始值
CF = 0; //清除TF0标志
CR = 0; //定时器0开始计时
fangbo();
CR = 1;
while((RX == 1) && (CH <= 0x20));
CR = 0;
if(RX == 0){
RX = 1;
time = (CH << 8) | CL;
distance = time * 0.017;
}
}
//************************************
//************************************显示功能
void cejujiemian(){//测距界面
showsmg(1,Seg_Table[10]);
showsmg(8,Seg_Table[distance % 10]);
if(distance > 9){
showsmg(7,Seg_Table[distance / 10 % 10]);
}
if(distance > 99){
showsmg(6,Seg_Table[distance / 100 % 10]);
}
}
void canshujiemian(){
showsmg(1,0x8c);
if(canshu){
showsmg(2,Seg_Table[2]);
}else{
showsmg(2,Seg_Table[1]);
}
showsmg(4,Seg_Table[canshuxiaxian / 10]);
showsmg(5,Seg_Table[canshuxiaxian % 10]);
showsmg(6,Seg_Table[16]);
showsmg(7,Seg_Table[canshushangxian / 10]);
showsmg(8,Seg_Table[canshushangxian % 10]);
}
void jilujiemian(){
showsmg(1,Seg_Table[14]);
if(baojingcishu < 10){
showsmg(8,Seg_Table[baojingcishu]);
}else{
showsmg(8,Seg_Table[16]);
}
}
//************************************
//************************************
void showselect(){
switch(show){
case 0:cejujiemian();break;
case 1:canshujiemian();break;
case 2:jilujiemian();break;
}
}
//************************************
//************************************按键扫描
void xuanniu(unsigned char channel){
voltage = RB2();
if(canshu){
if(channel == 0){
if(voltage < 51){
canshushangxian = 50;
}else if((51 <= voltage) && (voltage < 102)){
canshushangxian = 60;
}else if((102 <= voltage) && (voltage < 153)){
canshushangxian = 70;
}else if((153 <= voltage) && (voltage < 204)){
canshushangxian = 80;
}else if((204 <= voltage) && (voltage <= 255)){
canshushangxian = 90;
}
}
if(channel == 1){
if(voltage < 51){
canshuxiaxian = 0;
}else if((51 <= voltage) && (voltage < 102)){
canshuxiaxian = 10;
}else if((102 <= voltage) && (voltage < 153)){
canshuxiaxian = 20;
}else if((153 <= voltage) && (voltage < 204)){
canshuxiaxian = 30;
}else if((204 <= voltage) && (voltage <= 255)){
canshuxiaxian = 40;
}
}
}
}
void scankey(){
P33 = 0;P32 = 1;P44 = 1;P42 = 1;
if(P44 == 0){Delay(de);//S4
while(P44 == 0){ceju();showselect();}
show++;
show %= 3;
canshu = 0;
}
if(P42 == 0){Delay(de);//S8
while(P42 == 0){xuanniu(0);ceju();showselect();}
if((show == 1) && (canshu == 0)){
canshuxiaxian += 10;
canshuxiaxian %= 50;
}
}
P33 = 1;P32 = 0;P44 = 1;P42 = 1;
if(P44 == 0){Delay(de);//S5
while(P44 == 0){ceju();showselect();}
if(show == 1){
canshu = ~canshu;
}
if(show == 2){
baojingcishu = 0;
}
}
if(P42 == 0){Delay(de);//S9
while(P42 == 0){xuanniu(1);ceju();showselect();}
if((show == 1) && (canshu == 0)){
canshushangxian += 10;
if(canshushangxian > 90){canshushangxian = 50;}
}
}
}
//************************************
//************************************定时器配置闪烁
void Timer0_Isr(void) interrupt 1
{
count++;
if(count == 20){
flag2 = ~flag2;
count = 0;
}
}
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;
}
//************************************
//************************************LED
void julicanshupanduan(){//距离参数判断
if((distance <= canshuxiaxian) || (distance >= canshushangxian)){
if(flag == 0){
flag = 1;
baojingcishu++;
}
}
}
void led(){
if(show == 0){
ledstat = ledstat & ~0x01;
}else{
ledstat = ledstat | 0x01;
}
if(show == 1){
ledstat = ledstat & ~0x02;
}else{
ledstat = ledstat | 0x02;
}
if(show == 2){
ledstat = ledstat & ~0x04;
}else{
ledstat = ledstat | 0x04;
}
if((distance >= canshuxiaxian) && (distance <= canshushangxian)){
ledstat = ledstat & ~0x80;
flag = 0;
}else{
if(flag2){
ledstat = ledstat & ~0x80;
}else{
ledstat = ledstat | 0x80;
}
}
outputp0(4,ledstat);
}
//************************************
//************************************
void main(){
initpca();
initsys();
ceju();
Timer0_Init();
while(1){
ceju();
julicanshupanduan();
scankey();
showselect();
voltage = RB2();
Delay(1);
led();
}
}