写在前面:做完总体来说感觉一年比一年难了(估计是被骂的),虽然十三届用的底层少,但是做起来困难重重。

最难的难点在于定时器安排问题。15F2K60S2系列单片机只有三个定时器,本届题目考到了频率测量、超声波、PWM输出,再加上刷新,每一个都需要一个定时器,比较简单的做法之一是直接用单片机外设PCA来检测超声波,节省定时器资源。(b站上有个up主是切换定时器0计数/定时模式来实现的,这样也可以,但是个人感觉比较麻烦,也容易出现问题)

对于NE555频率测量,要求是P3^4进行脉冲输入,正好是T0输出,所以最好是用定时器0,当然也可以使用其它定时器,这样就需要使用sbit函数定义P3^4引脚,相对比较麻烦。

定时器0:频率计数;定时器1:函数刷新;定时器2:PWM输出。

1、首先是NE555频率测量:

其中TMOD|=0x04为切换定时器为计数模式。

2、其次是PCA实现超声波测量:

(别忘了TX、RX引脚定义)

 

 最后得到的值+3(实际测量在+2.5左右),原因是因为硬件或者程序延时时间等问题有小误差,很多博主和教程里这个地方都有加3,可以自己拿尺子测量一下距离看看是不是这样。

 3、PWM输出

首先看题目:

 首先找到这个电机驱动引脚连接的位置:(不是去找J3哦)

 可以发现它和我们常用的继电器、蜂鸣器在一个地方,这样我们就可以像控制它俩一样控制电机。

输出频率为1khz,那么我们输出信号周期就为1000微秒,分成5份,每份就是200微秒,就可以设置200微秒定时器中断。

 这里每份是200微秒,那么之前我们设置的超声波程序整个过程是24微秒*8=192微秒<200微秒,这样才不会因为关闭中断时间过长造成PWM输出异常。

4、PCF8591

这里我设置采集时关闭中断,完成后才打开,以免影响iic时序。如果不关闭的话,实际采集值会来回跳变(大家可以试一试是不是这样),有的教程和博主教学里面没关,可能是我其它程序设置问题。

注意:设置的外设等刷新时间,应该是满足条件的最大值,以免多次采集造成不良影响。

 自从第十届开始,采取机器阅卷后,就对采集时间等等性能有姚桥,但本届题目并没有和省赛一样设置外设时间刷新要求,原因可能是超声波、频率等等容易冲突的地方太多了,就放宽了条件,所以我们在设置刷新时间,就适当的加长一点。

 

完整题目:

 

 

 

 

 

 

完整程序: 

MAIN.c

#include

#include

#include "sonic.h"

void Task_Clock(void)

{

Set_HC573(4,LED);

Set_HC573(5,Actuator_Bit);

if(LED_flag==1){if(++LED_tt == 100)

{

LED_tt = 0;

if(LED_Run==1){LED_ON(State3);LED_Run=0;}

else if(LED_Run==0){LED_OFF(State3);LED_Run=1;}}

}

if(++SEG_tt == 50) { SEG_tt = 0; SEG_Ref = 1; }

if(++KEY_tt == 10) { KEY_tt = 0; KeyScan(); }

if(++AD_tt == 300) { AD_tt = 0; AD_Ref = 1; }

if(++LCM_tt == 500) {LCM_tt = 0; LCM_Ref = 1; }

if(++Freq_tt == 1000) {Freq_tt = 0; Freq_Ref = 1; }

}

void main(void)

{

ALL_Init();

if(AT24C02_read(0X64)!=0x80)

{

AT24C02_write(0x64,0x80);Delay_MS(5);

AT24C02_write(0x00,0);Delay_MS(5);

}

else {Cishu = AT24C02_read(0X00); Delay_MS(5);}

LED_ON(1);

AD_read(0X43);

AD_Value = AD_read(0X43);

AD_Value = AD_Value * 1.96;

Timer0Init();

Timer1Init();

Timer2Init();IE2 |= 0X04;

EA = 1; ET1 = 1;

while(1)

{

if(SEG_Ref == 1)

{

SEG_Ref = 0;

SEG_Refresh();

}

if(KEY_Flag == 1)

{

KEY_Flag = 0;

Task_Key();

}

if(AD_Ref == 1)

{

AD_Ref = 0;

AD_Value = AD_read(0X43); //滑动变阻器0X03,光敏电阻0X01

AD_Value = AD_Value * 1.96;

Shidu=0.2*AD_Value;

if(Shidu<=Shidu_para){AD_write(51);LED_OFF(5);}

else if(Shidu>=80){AD_write(255);LED_ON(5);}

else {AD_write((Shidu-80)*4*51/(80-Shidu_para)+5*51);LED_ON(5);}

}

if(LCM_Ref == 1)

{

LCM_Ref = 0;

LCM=Sonic_Measure()+3;

if((LCM>LCM_para*10)&&(LCM_last<=LCM_para*10))

{

Actuator_Bit|=0x10;Cishu=Cishu+1;AT24C02_write(0x00,Cishu);LED_ON(6);

}

else if((LCM>LCM_para*10)&&(LCM_last>LCM_para*10))

{

LED_ON(6);

}

else if(LCM<=LCM_para*10){Actuator_Bit&=~0x10;LED_OFF(6);}

LCM_last=LCM;

}

if(Freq_Ref == 1)

{

Freq_Ref = 0 ;

Freq_Callback_1s();

if(Freq>Freq_para*100)

{

LED_ON(4);

PWM_Deuty_count=4;

}

else

{

LED_OFF(4);

PWM_Deuty_count=1;

}

}

}

}

void Task_Key(void)

{

if(KEY_Value==4)

{

KEY_Value=0;

if(SEG_Show==1){SEG_Show=2;LED_OFF(1);LED_ON(2);}

else if(SEG_Show==2){SEG_Show=3;LED_OFF(2);LED_ON(3);}

else if(SEG_Show==3){SEG_Show=4;LED_OFF(3);State3=1;LED_flag=1;}

else if(SEG_Show==4){SEG_Show=1;LED_flag=0;LED_OFF(State3);LED_ON(1);}

}

if(KEY_Value==5)

{

KEY_Value=0;

if(SEG_Show==4)

{

if(State3==1){State3=2;LED_OFF(1);}

else if(State3==2){State3=3;LED_OFF(2);}

else if(State3==3){State3=1;LED_OFF(3);}

}

}

if(KEY_Value==6){

KEY_Value=0;

if(SEG_Show==4)

{

if(State3==1)

{

Freq_para=Freq_para+5;

if(Freq_para>120)Freq_para=10;

}

else if(State3==2)

{

Shidu_para=Shidu_para+10;

if(Shidu_para>60)Shidu_para=10;

}

else if(State3==3)

{

LCM_para=LCM_para+1;

if(LCM_para>12)LCM_para=1;

}

}

if(SEG_Show==3)

{

if(State2==1)State2=2;

else State2=1;

}

}

if((KEY_Value==7)&&(KEY_Press_TIME<1000))

{

KEY_Value=0;

if(SEG_Show==4)

{

if(State3==1)

{

Freq_para=Freq_para-5;

if(Freq_para<10)Freq_para=120;

}

else if(State3==2)

{

Shidu_para=Shidu_para-10;

if(Shidu_para<10)Shidu_para=60;

}

else if(State3==3)

{

LCM_para=LCM_para-1;

if(LCM_para<1)LCM_para=12;

}

}

if(SEG_Show==1)

{

if(State1==1)State1=2;

else State1=1;

}

}

if((KEY_Value==7)&&(KEY_Press_TIME>=1000))

{

KEY_Value=0;

Cishu=0;

AT24C02_write(0x00,0);

}

}

void SEG_Refresh(void)

{

if(SEG_Show == 1)

{

DigBuf[0] = 22; DigBuf[1] = 21; DigBuf[2] = 21;

if(State1==1)

{

if(Freq>=10000)

{

DigBuf[3]=Freq/10000;

DigBuf[4]=Freq%10000/1000;

DigBuf[5]=Freq%1000/100;

DigBuf[6]=Freq%100/10;

DigBuf[7]=Freq%10;

}

else if((Freq>=1000)&&(Freq<10000))

{

DigBuf[3]=21;

DigBuf[4]=Freq%10000/1000;

DigBuf[5]=Freq%1000/100;

DigBuf[6]=Freq%100/10;

DigBuf[7]=Freq%10;

}

else if((Freq>=100)&&(Freq<1000))

{

DigBuf[3]=21;

DigBuf[4]=21;

DigBuf[5]=Freq%1000/100;

DigBuf[6]=Freq%100/10;

DigBuf[7]=Freq%10;

}

else if((Freq>=10)&&(Freq<100))

{

DigBuf[3]=21;

DigBuf[4]=21;

DigBuf[5]=21;

DigBuf[6]=Freq%100/10;

DigBuf[7]=Freq%10;

}

}

else if(State1==2)

{

DigBuf[3]=21;

DigBuf[4]=21;

if(Freq>=10000)

{

DigBuf[5]=Freq/10000;

DigBuf[6]=Freq/1000%10+10;

DigBuf[7]=Freq/100%10;

}

else if((Freq>=1000)&&(Freq<10000))

{

DigBuf[5]=21;

DigBuf[6]=Freq/1000%10+10;

DigBuf[7]=Freq/100%10;

}

else if((Freq>=100)&&(Freq<1000))

{

DigBuf[5]=21;

DigBuf[6]=10;

DigBuf[7]=Freq/100%10;

}

}

}

else if(SEG_Show == 2)

{

DigBuf[0] = 23; DigBuf[1] = 21;

DigBuf[2] = 21; DigBuf[3] = 21; DigBuf[4] = 21;

DigBuf[5] = 21; DigBuf[6] = Shidu/ 10; DigBuf[7] = Shidu % 10;

}

else if(SEG_Show == 3)

{

DigBuf[0] = 24; DigBuf[1] = 21; DigBuf[2] = 21;

DigBuf[3] = 21; DigBuf[4] = 21;

if(State2==1)

{

if(LCM>=100)

{

DigBuf[5] = LCM/100;

DigBuf[6] = LCM%100/10;

DigBuf[7] = LCM%10;

}

else if((LCM>=10)&&(LCM<100))

{

DigBuf[5] = 21;

DigBuf[6] = LCM%100/10;

DigBuf[7] = LCM%10;

}

else if((LCM>=0)&&(LCM<10))

{

DigBuf[5] = 21;

DigBuf[6] = 21;

DigBuf[7] = LCM%10;

}

}

else if(State2==2)

{

if(LCM>=100)

{

DigBuf[5] = LCM/100+10;

DigBuf[6] = LCM%100/10;

DigBuf[7] = LCM%10;

}

else if((LCM>=10)&&(LCM<100))

{

DigBuf[5] = 10;

DigBuf[6] = LCM%100/10;

DigBuf[7] = LCM%10;

}

else if((LCM>=0)&&(LCM<10))

{

DigBuf[5] = 10;

DigBuf[6] = 0;

DigBuf[7] = LCM%10;

}

}

}

else if(SEG_Show == 4)

{

DigBuf[0]=25;DigBuf[1]=State3;

DigBuf[2]=21;

DigBuf[3]=21;

DigBuf[4]=21;

if(State3==1)

{

if(Freq_para>=100)

{

DigBuf[5]=Freq_para%1000/100;

DigBuf[6]=Freq_para%100/10+10;

DigBuf[7]=Freq_para%10;

}

else

{

DigBuf[5]=21;

DigBuf[6]=Freq_para%100/10+10;

DigBuf[7]=Freq_para%10;

}

}

else if(State3==2)

{

DigBuf[5]=21;

DigBuf[6]=Shidu_para%100/10;

DigBuf[7]=Shidu_para%10;

}

else if(State3==3)

{

DigBuf[5]=21;

DigBuf[6]=LCM_para%100/10+10;

DigBuf[7]=LCM_para%10;

}

}

}

void Delay12us() //@12.000MHz

{

unsigned char i;

_nop_();

_nop_();

i = 33;

while (--i);

}

// 使用PCA模块计时,Sysclk不分频做时钟输入

void Sonic_Init()

{

CMOD = 0x88;

CCON = 0;

CH = 0;

CL = 0;

}

void Sonic_SendTrig()

{

unsigned char i;

// 关中断发驱动波形

EA = 0;

for (i = 0; i < 8; i++) {

TX = 1;

Delay12us();

TX = 0;

Delay12us();

}

EA = 1;

}

unsigned int Sonic_Measure()

{

unsigned char cf = 0;

Sonic_Init();

Sonic_SendTrig();

// 开始计时

CR = 1;

while (RX) {

// 计数器溢出处理

if (CF == 1) {

cf++;

CF = 0;

}

if (cf == 10) {

CR = 0;

return 65535;

}

}

CR = 0;

// (((CH * 256 + CL) * 0.017) / 12:本轮计数的距离

// 92.8427 * cf:溢出计数距离

return (unsigned int ) (((CH * 256 + CL) * 0.017) / 12 + 92.8427 * cf);

}

void KeyScan(void)

{

switch(KeyState)

{

case KEY_Check: if((P30 == 0) || (P31 == 0) || (P32 == 0) || (P33 == 0)) KeyState = KEY_Press;break;

case KEY_Press:

{

if(P30 == 0) KEY_Value = 7;

else if(P31 == 0) KEY_Value = 6;

else if(P32 == 0) KEY_Value = 5;

else if(P33 == 0) KEY_Value = 4;

KeyState = KEY_Release;

KEY_Press_TIME = 10;

}

break;

case KEY_Release:

{

if((P30 == 0) || (P31 == 0) || (P32 == 0) || (P33 == 0))

{

KEY_Press_TIME = KEY_Press_TIME + 10;

}

else

{

KeyState = KEY_Check;

KEY_Flag = 1;

}

}

break;

default: break;

}

}

void Timer2(void) interrupt 12

{

EA=0;

if(PWM_count==0)Actuator_Bit|= 0x20;

else if(PWM_count == PWM_Deuty_count ) { Actuator_Bit&=~0x20; }

else if(PWM_count == 5 ) { PWM_count = 0; Actuator_Bit|= 0x20; }

Set_HC573(5,Actuator_Bit);

EA=1;

PWM_count++;

}

void Timer2Init(void) //200微秒@12.000MHz

{

AUXR |= 0x04; //定时器时钟1T模式

T2L = 0xA0; //设置定时初始值

T2H = 0xF6; //设置定时初始值

AUXR |= 0x10; //定时器2开始计时

}

void Timer1(void) interrupt 3

{

Set_HC573(6,0x00);

Set_HC573(7,tab[DigBuf[DigCom]]);

Set_HC573(6,0x01<

if(++DigCom==8)DigCom=0;

Task_Clock();

}

void Timer1Init(void) //1毫秒@12.000MHz

{

AUXR |= 0x40; //定时器时钟1T模式

TMOD &= 0x0F; //设置定时器模式

TL1 = 0x20; //设置定时初始值

TH1 = 0xD1; //设置定时初始值

TF1 = 0; //清除TF1标志

TR1 = 1; //定时器1开始计时

}

void Timer0Init(void) //@12.000MHz

{

AUXR |= 0x80; //定时器时钟1T模式

TMOD |= 0x04; //设置定时器模式

TL0 = 0x00; //设置定时初始值

TH0 = 0x00; //设置定时初始值

TF0 = 0; //清除TF0标志

}

void Freq_Callback_1s()

{

TR0 = 0;

Freq = TH0 * 256 + TL0;

TL0 = 0x0;

TH0 = 0x0;

TF0 = 0;

TR0 = 1;

}

void All_Init()

{

Set_HC573(5,0x00);

Set_HC573(4,0xff);

Set_HC573(6,0x00);

}

void Set_HC573(unsigned char channel,unsigned char dat)

{

P0=dat;

switch(channel)

{

case 4:

P2=0x80;

break;

case 5:

P2=0xa0;

break;

case 6:

P2=0xc0;

break;

case 7:

P2=0xe0;

break;

}

P2=0;

}

void Delay_MS(unsigned int MS) //@12.000MHz

{

unsigned int k;

unsigned char i, j;

for(k=0;k

{

i = 12;

j = 169;

do

{

while (--j);

} while (--i);

}

}

MAIN.h程序

#ifndef __MAIN_H__

#define __MAIN_H__

#include

#include

sbit TX = P1^0 ;

sbit RX = P1^1 ;

unsigned char LED=0xff;

unsigned char Actuator_Bit = 0X00;

unsigned char code tab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,\

0X40,0X79,0X24,0X30,0X19,0X12,0X02,0X78,0X00,0X10,\

0XBF,0XFF,0x8e,0x89,0x88,0x8c};

#define LED_ON(n) {LED&=~(0x01<<(n-1)); }

#define LED_OFF(n) {LED|=(0x01<<(n-1));}

unsigned char DigCom = 0 ;

unsigned char DigBuf[8] = {21,21,21,21,21,21,21,21};

typedef enum

{

KEY_Check, //检测状态

KEY_Press, //按下状态

KEY_Release, //等待松开状态

Key_Over //按下之后松开,按键结束状态

}KEY_State;

KEY_State KeyState = KEY_Check; //初始设置按键初始化状态为检测状态

unsigned char KEY_Value = 0;

unsigned char KEY_tt = 0; //按键扫描时间计时

unsigned int KEY_Press_TIME = 10; //按键按下时长

bit KEY_Flag = 0; //按键按下又松开之后标识位

unsigned int LED_tt = 0 ;

bit LED_Ref =0;

unsigned int SEG_tt =0;

bit SEG_Ref = 0 ;

unsigned int AD_Value = 0;

unsigned int AD_tt = 0;

bit AD_Ref = 0;

unsigned int LCM_tt = 0 ;

bit LCM_Ref = 0 ;

unsigned int LCM = 0 ;

unsigned int LCM_last=0;

unsigned int xdata PWM_count = 0;

unsigned char xdata PWM_Deuty_count = 0;

unsigned int Freq = 0;

unsigned int Freq_tt = 0;

bit Freq_Ref = 0;

unsigned char SEG_Show = 1 ;

unsigned int Cishu=0;

unsigned char State1=1;

unsigned char State2=1;

unsigned char State3=1;

unsigned char Shidu=0;

unsigned char Freq_para=90;

unsigned char Shidu_para=40;

unsigned char LCM_para=6;

bit LED_flag=0;

bit LED_Run=0;

void Delay_MS(unsigned int MS);

void Set_HC573(unsigned char channel,unsigned char dat);

void ALL_Init(void);

void Timer0Init(void); //1毫秒@12.000MHz

void KeyScan(void);

void Task_Clock(void);

void SEG_Refresh(void);

void Task_Key(void);

void Delay12us(); //@12.000MHz

void Timer1Init(void); //10微秒@12.000MHz

void Sonic_Init() ;

void Sonic_SendTrig() ;

void Freq_Callback_1s() ;

void Timer2Init();

#endif

IIC.c程序

#include

#include "intrins.h"

//总线引脚定义

sbit sda = P2^1; /* 数据线 */

sbit scl = P2^0; /* 时钟线 */

#define DELAY_TIME 5

//

static void I2C_Delay(unsigned char n)

{

do

{

_nop_();

// _nop_();_nop_();_nop_();_nop_();

// _nop_();_nop_();_nop_();_nop_();_nop_();

// _nop_();_nop_();_nop_();_nop_();_nop_();

}

while(n--);

}

//

void I2CStart(void)

{

sda = 1;

scl = 1;

I2C_Delay(DELAY_TIME);

sda = 0;

I2C_Delay(DELAY_TIME);

scl = 0;

}

//

void I2CStop(void)

{

sda = 0;

scl = 1;

I2C_Delay(DELAY_TIME);

sda = 1;

I2C_Delay(DELAY_TIME);

}

//

void I2CSendByte(unsigned char byt)

{

unsigned char i;

for(i=0; i<8; i++){

scl = 0;

I2C_Delay(DELAY_TIME);

if(byt & 0x80){

sda = 1;

}

else{

sda = 0;

}

I2C_Delay(DELAY_TIME);

scl = 1;

byt <<= 1;

I2C_Delay(DELAY_TIME);

}

scl = 0;

}

//

unsigned char I2CReceiveByte(void)

{

unsigned char da;

unsigned char i;

for(i=0;i<8;i++){

scl = 1;

I2C_Delay(DELAY_TIME);

da <<= 1;

if(sda)

da |= 0x01;

scl = 0;

I2C_Delay(DELAY_TIME);

}

return da;

}

//

unsigned char I2CWaitAck(void)

{

unsigned char ackbit;

scl = 1;

I2C_Delay(DELAY_TIME);

ackbit = sda;

scl = 0;

I2C_Delay(DELAY_TIME);

return ackbit;

}

//

void I2CSendAck(unsigned char ackbit)

{

scl = 0;

sda = ackbit;

I2C_Delay(DELAY_TIME);

scl = 1;

I2C_Delay(DELAY_TIME);

scl = 0;

sda = 1;

I2C_Delay(DELAY_TIME);

}

unsigned char AT24C02_read(unsigned char add)

{

unsigned char da;

I2CStart();

I2CSendByte(0XA0);

I2CWaitAck();

I2CSendByte(add);

I2CWaitAck();

I2CStop();

I2CStart();

I2CSendByte(0XA1);

I2CWaitAck();

da = I2CReceiveByte();

I2CSendAck(1);

I2CStop();

return da;

}

void AT24C02_write(unsigned char add,unsigned char dat)

{

I2CStart();

I2CSendByte(0xA0);

I2CWaitAck();

I2CSendByte(add);

I2CWaitAck();

I2CSendByte(dat);

I2CWaitAck();

I2CStop();

}

unsigned char AD_read(unsigned char add)

{

unsigned char temp;

EA=0;

I2CStart();

I2CSendByte(0X90);

I2CWaitAck();

I2CSendByte(add);

I2CWaitAck();

I2CStop();

I2CStart();

I2CSendByte(0X91);

I2CWaitAck();

temp=I2CReceiveByte();

I2CSendAck(1);

I2CStop();

EA=1;

return temp;

}

void AD_write(unsigned char dat)

{

EA=0;

I2CStart();

I2CSendByte(0X90);

I2CWaitAck();

I2CSendByte(0X40);

I2CWaitAck();

I2CSendByte(dat);

I2CWaitAck();

I2CStop();

EA=1;

}

IIC.h程序

#ifndef _IIC_H

#define _IIC_H

static void I2C_Delay(unsigned char n);

void I2CStart(void);

void I2CStop(void);

void I2CSendByte(unsigned char byt);

unsigned char I2CReceiveByte(void);

unsigned char I2CWaitAck(void);

void I2CSendAck(unsigned char ackbit);

unsigned char AT24C02_read(unsigned char add);

void AT24C02_write(unsigned char add,unsigned char dat);

unsigned char AD_read(unsigned char add);

void AD_write(unsigned char dat);

#endif

精彩内容

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: