1、 基本要求
1.1 使用大赛组委会提供的国信长天单片机竞赛实训平台,完成本试题的程序设计与调试。
1.2 选手在程序设计与调试过程中,可参考组委会提供的“资源数据包”。
1.3 请注意: 程序编写、调试完成后选手应通过考试系统提交完整、可编译的 Keil工程文件。 选手提交的工程文件应是最终版本, 要求 Keil 工程文件以准考证号( 8 位数字)命名,工程文件夹内应包含以准考证号命名的 hex 文件,该 hex文件是成绩评审的依据。 不符合以上文件提交要求的作品将被评为零分或者被酌情扣分。
1.4 请勿上传与作品工程文件无关的其它文件。
2、 竞赛板配置要求
2.1 将 IAP15F2K61S2 单片机内部振荡器频率设定为 12MHz。
2.2 键盘工作模式跳线 J5 配置为 BTN 独立按键模式。
2.3 扩展方式跳线 J13 配置为 IO 模式。
2.4 请注意: 选手需严格按照以上要求配置竞赛板,编写和调试程序, 不符合以上配置要求的作品将被评为零分或者被酌情扣分。
3、 硬件框图
4、 功能描述
4.1基本功能
4.3按键功能
4.4LED 指示灯功能
4.5初始状态说明
主函数
#include "stc15f2k60s2.h"
#include "iic.h"
typedef unsigned char uchar;
typedef unsigned int uint;
uchar code SMG_TAB[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
uchar SMG_WEI[]={0X01,0X02,0X04,0X08,0X10,0X20,0X40,0X80};
uchar DAC_display[8];
uchar Freq_display[8];
uint DAC_val; //注意取值范围(超过255)
long Freq_val; //频率值
uchar mode_display;
uchar voltage_flag; //选择电压
uchar led_enable; //LED功能启用
uchar SMG_enable; //数码管启用
bit flag500ms; //频率刷新时间
bit flag200ms; //电压刷新时间
uchar led=0xff,LEDDAT=0XFF;
uchar key_init();
void Timer1Init(); //1毫秒@11.0592MHz
void Timer0Init();
void DAC_display_init(); //电压
void Freq_display_init(); //频率
void LED_init(); //LED
void All_init() //板子初始化
{
P2=(P2&0X1F)|0XA0;
P0=0X00;
P2=(P2&0X1F)|0X80;
P0=0XFF;
P2=P2&0X1F;
}
void ledlight()
{
P0=0XFF;
P2=(P2&0X1F)|0X80;
P0=led;
P2=P2&0X1F;
}
void main()
{
uchar key_val;
All_init();
Timer0Init();
Timer1Init();
write_dac(0x03);
while(1)
{
P2=0X80;
DAC_display_init();
Freq_display_init();
LED_init();
key_val=key_init();
switch(key_val)
{
case 4: //模式选择
mode_display++;
if(mode_display==2)
mode_display=0;
break;
case 5: //电压测量选择
voltage_flag++;
if(voltage_flag==2)
voltage_flag=0;
break;
case 6: //LED使能
led_enable++;
if(led_enable==2)
led_enable=0;
break;
case 7:
SMG_enable++;
if(SMG_enable==2)
SMG_enable=0;
break;
}
}
}
void DAC_display_init()
{
if(flag200ms)
{
flag200ms=0;
if(voltage_flag==0)
{
DAC_out(102.4);
DAC_val=200;
}
else
{
DAC_val=read_dac(0x03)/0.51f;
}
}
DAC_display[0]=0x3e; DAC_display[1]=0x00;
DAC_display[2]=0x00; DAC_display[3]=0x00;
DAC_display[4]=0x00; DAC_display[5]=SMG_TAB[DAC_val/100]|0x80;
DAC_display[6]=SMG_TAB[DAC_val/10%10]; DAC_display[7]=SMG_TAB[DAC_val%10];
}
void Freq_display_init()
{
if(flag500ms)
{
flag500ms=0;
TR0 = 0; //关闭定时器0计数
Freq_val = TH0 * 256 + TL0; //统计500ms内脉冲数
Freq_val *= 2; //乘以2就是1s内脉冲数,就是频率
TH0 = TL0 = 0; //清除定时器0计数数据
TR0 = 1; //定时器0重新开始计数
}
Freq_display[0]=0x71; Freq_display[1]=0x00;
if(Freq_val>99999)
Freq_display[2]=SMG_TAB[Freq_val/100000];
else
Freq_display[2]=0x00;
if(Freq_val>9999)
Freq_display[3]=SMG_TAB[Freq_val/10000%10];
else
Freq_display[3]=0x00;
if(Freq_val>999)
Freq_display[4]=SMG_TAB[Freq_val/1000%10];
else
Freq_display[4]=0x00;
if(Freq_val>99)
Freq_display[5]=SMG_TAB[Freq_val/100%10];
else
Freq_display[5]=0x00;
if(Freq_val>9)
Freq_display[6]=SMG_TAB[Freq_val/10%10];
else
Freq_display[6]=0x00;
Freq_display[7]=SMG_TAB[Freq_val%10];
}
void LED_init()
{
if(led_enable==0) //LED功能允许
{
switch(mode_display)
{
case 0:
LEDDAT=0xfe; //测压 L1亮
break;
case 1:
LEDDAT=0xfd; //测频 L2亮
break;
}
if(mode_display==0) //电压测量
{
if(voltage_flag==1) //不是固定输出2.0V
{
LEDDAT=0XEE; //L5亮
//关闭L4
if(DAC_val<150)
{
LEDDAT=0XEE; //关闭L3
}
else if((DAC_val>=150)&&(DAC_val<250))
{
LEDDAT=0XEA; //打开L3
}
else if((DAC_val>=250)&&(DAC_val<350))
{
LEDDAT=0XEE; //关闭L3
}
else
{
LEDDAT=0XEA; //打开L3
}
}
else //是固定输出2.0V
{
LEDDAT=0XFE; //关闭L5
}
}
if(mode_display==1) //频率测量
{
if(Freq_val<1000)
LEDDAT=0xfd;
else if((Freq_val>=1000)&&(Freq_val<5000))
LEDDAT=0xf5;
else if((Freq_val>=5000)&&(Freq_val<10000))
LEDDAT=0xfd;
else
LEDDAT=0xf5;
}
}
else
LEDDAT=0xff; //led功能禁止
led=LEDDAT;
}
void Timer1Init() //1毫秒@11.0592MHz
{
AUXR |= 0x40; //定时器时钟1T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0xCD; //设置定时初值
TH1 = 0xD4; //设置定时初值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
EA=1;
ET1=1;
}
void Timer0Init()
{
AUXR &= 0x7F; //定时器时钟1T模式
TMOD = 0x04; //设置定时器0为16位自动重装载外部记数模式
TH0 = TL0 = 0; //设置定时器0初始值
TR0 = 1; //定时器0开始工作
EA=1;
ET0=1;
}
void timer1() interrupt 3
{
uchar i;
uchar SMG_count;
uint fre_count,vol_count;
SMG_count++;
fre_count++;
vol_count++;
if(fre_count==500) //频率刷新时间0.5s
{
fre_count=0;
flag500ms=1;
}
if(vol_count==200) //电压刷新时间0.2s
{
vol_count=0;
flag200ms=1;
}
if(SMG_count==3)
{
SMG_count=0;
if(SMG_enable==0)
{
P2=(P2&0X1F)|0XC0; P0=0X00;
P2=(P2&0X1F)|0XC0; P0=SMG_WEI[i];
P2=P2&0X1F;
if(mode_display==0) //电压测量
{
P2=(P2&0X1F)|0XE0;
P0=~DAC_display[i];
P2=P2&0X1F;
}
if(mode_display==1) //频率测量
{
P2=(P2&0X1F)|0XE0;
P0=~Freq_display[i];
P2=P2&0X1F;
}
}
else
{
P2=(P2&0X1F)|0XC0; P0=0X00;
P2=(P2&0X1F)|0XC0; P0=SMG_WEI[i];
P2=(P2&0X1F)|0XE0; P0=0XFF;
P2=P2&0X1F;
}
i++;
if(i==8)
i=0;
}
ledlight();
}
按键模块
#define key_state0 0
#define key_state1 1
#define key_state2 2
uchar key_init()
{
static uchar key_state=0;
uchar key_press,key_return=0;
key_press=P3&0X0F;
switch(key_state)
{
case key_state0:
if(key_press!=0x0f)
key_state=key_state1;
break;
case key_state1:
if(key_press!=0x0f)
{
if(key_press==0x0e) key_return=7;
if(key_press==0x0d) key_return=6;
if(key_press==0x0b) key_return=5;
if(key_press==0x07) key_return=4;
key_state=key_state2;
}
else
key_state=key_state0;
break;
case key_state2:
if(key_press==0x0f)
key_state=key_state0;
break;
}
return key_return;
}
PCF8591模块
/*
程序说明: IIC总线驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台(12MHz)
日 期: 2011-8-9
*/
#include "iic.h"
void iic_delay(unsigned char ms)
{
do
{
_nop_();
}while(ms--);
}
//总线启动条件
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
iic_delay(5);
SDA = 0;
iic_delay(5);
SCL = 0;
}
//总线停止条件
void IIC_Stop(void)
{
SDA = 0;
SCL = 1;
iic_delay(5);
SDA = 1;
}
/*IIC总线协议规定,每传送一个字节数据后,都要有一个应答信号,以确定数据传送是否被对方收到,
应答信号由接收设备产生,在SCL为高电平期间,接收设备将SDA拉为低电平表示数据传输正确,即产生了应答。*/
//应答位控制
void IIC_Ack(unsigned char ackbit) //当ackbit为1时,表示单片机对从设备发送来数据的应答
//当ackbit为0时,表示主机接收了最后一个字节,因此不再应答,结束通信
{
if(ackbit)
{
SDA = 0;
}
else
{
SDA = 1;
}
iic_delay(5);
SCL = 1;
iic_delay(5);
SCL = 0;
SDA = 1;
iic_delay(5);
}
//等待应答
bit IIC_WaitAck(void)
{
SDA = 1;
iic_delay(5);
SCL = 1;
iic_delay(5);
if(SDA) //在SCL为高电平期间,因为接收设备未将SDA拉低,所以默认未接收到应答,结束IIC通信
{
SCL = 0;
IIC_Stop();
return 0;
}
else //接收到应答,返回1,继续下一个数据字节的传输
{
SCL = 0;
return 1;
}
}
//通过I2C总线发送数据
void IIC_SendByte(unsigned char byt)
{
unsigned char i;
for(i=0;i<8;i++)
{
if(byt&0x80)
{
SDA = 1;
}
else
{
SDA = 0;
}
iic_delay(5);
SCL = 1;
byt <<= 1;
iic_delay(5);
SCL = 0;
}
}
//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
unsigned char da;
unsigned char i;
for(i=0;i<8;i++)
{
SCL = 1;
iic_delay(5);
da <<= 1;
if(SDA)
da |= 0x01;
SCL = 0;
iic_delay(5);
}
return da;
}
void write_dac(unsigned char dat)
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}
unsigned char read_dac(unsigned char dat)
{
unsigned char temp;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
temp=IIC_RecByte();
IIC_Ack(0);
IIC_Stop();
return temp;
}
void DAC_out(unsigned char dat) // D/A转换
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x40);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}
以上就是代码全部内容,欢迎交流,共同学习~
(喜欢就留个赞和关注再走吧~)