概述
目录
题目及其要求
考察模块
分析:
1、模块分析
2、题目要求分析
代码实现
1、主函数
2、I2C(AD)
题目及其要求
考察模块
- 三大金刚:LED,按键,数码管。
- 继电器。
- AD。
分析:
1、模块分析
定时器的生成:使用烧录软件stc-isp来实现。
void Timer0Init(void) //1毫秒@12.000MHz
{
EA=1;ET0=1; //一定!一定!一定!要开中断
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x20; //设置定时初值
TH0 = 0xD1; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
}
注意:一定要开中断,要不然后面数码管和按键都会没反应。
数码管段码和位码表的生成:使用烧录软件stc-isp来实现。
/************* 本地常量声明 **************/
u8 code t_display[]={ //标准字库
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
//black - H J K L N o P U t G Q r M y
0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46}; //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1
u8 code T_COM[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //位码
按键
因为只需要按键S7和S6,题目也明确要求,所以我采用独立按键的方式来实现按键S7和S6。
注:按键消抖采用定时器来实现,使用10ms进行消抖。
//独立按键的三行代码
void ReadKey()
{
ReadData=P3^0xff;
Trg= ReadData&(ReadData^Cont);
Cont= ReadData;
}
void dsp_key()
{
if(key_flag)
{
key_flag=0;
ReadKey();
switch(Trg)
{
case 0x02: //s6
....//按键功能实现代码
break;
case 0x01: //s7
....//按键功能实现代码
break;
}
}
}
数码管
数码管的动态扫描使用定时器实现,每2ms扫描一次。
if(++Smg_count>= 2 ) //2ms扫描刷新数码管
{
Smg_count=0;
P2=0xe0;P0=0xff;P2=0x00; //数码管消隐
P2=0xc0;P0=T_COM[i];P2=0x00; //位选
P2=0xe0;P0=~t_display[smg_table[i]];P2=0x00; //段选
i++;
if(i>=8)i=0;
}
LED
本次只使用L1实现亮灭,则:
L1灭: P2 = 0x80;P0 = 0xff; P2 = 0x00;
L1亮: P2 = 0x80;P0 = 0xfe; P2 = 0x00;
继电器
继电器打开和关闭
sbit buzzer = P0^6; //蜂鸣器
sbit relay = P0^4; //继电器
继电器关闭:P2 = 0xa0;buzzer = 0 ;relay = 0; P2 = 0x00;
继电器打开:P2 = 0xa0;buzzer = 0 ;relay = 1; P2 = 0x00;
AD
除了官方数据包里面给的iic代码,还需自己写的代码部分。
//写需要读取的地址
void write_adc(unsigned char add)
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_Stop();
}
//读取
unsigned char read_adc(unsigned char add)
{
unsigned char temp;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
temp=IIC_RecByte();
IIC_WaitAck();
IIC_Stop();
return temp;
}
2、题目要求分析
问题:
S7为出水控制按键,按下后,售水机持续出水(继电器接通,指示灯L10点亮)。
S6为停水控制按键,按下后,停止出水(继电器断开,指示灯L10熄灭)。
方法:设置一个标志mode,当mode=0为停水模式mode=1为出水模式,相应模式下继电器实现相应亮灭。
问题
假定水价为0.5 元/升,出水速度为100毫升/秒。
一次出水总量达到99.99L时,继电器自动断开,数码管显示DS2显示价格。
方法:出水速度为100毫升/秒将其转换为0.01L/100ms。
问题
通过光敏电阻RD1和AD转换芯片PCF8591组成的亮度检测电路(亮度值转换为PCF8591光敏电阻通道的电压)检测环境亮度;
当PCF8591光敏电阻通道输入电压小于1.25 V时, L1 点亮,大于1.25V时,L1熄灭。
方法:按照0~255对应0~5V,我们只需要将0~1.25V的对应值算出来,之后对读取的数据进行IF判断,就可以控制等来作显示信息了。
注意:这个要求得注意
代码实现
1、主函数
#include<stc15f2k60s2.h>
#include "iic.h"
#define u8 unsigned char
#define u16 unsigned int
sbit buzzer = P0^6; //蜂鸣器
sbit relay = P0^4; //继电器
/************* 本地常量声明 **************/
u8 code t_display[]={ //标准字库
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
//black - H J K L N o P U t G Q r M y
0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46}; //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1
u8 code T_COM[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //位码
u8 smg_table[]={16,16,16,16,16,16,16,16}; //black
u8 ReadData,Trg,Cont;
u16 water_number=0,water_price=0; //水量和水费
u16 Voltage; //光敏电阻电阻值
bit mode; //mode=0为停水模式mode=1为出水模式
bit key_flag,flag; //扫描按键标志位和出水量清除标志
void Close_Peripherals ()
{
P2 = 0x80;P0 = 0xff; P2 = 0x00;
P2 = 0xa0;buzzer = 0 ;relay = 0; P2 = 0x00;
}
void Timer0Init(void) //1毫秒@12.000MHz
{
EA=1;ET0=1;
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x20; //设置定时初值
TH0 = 0xD1; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
}
void Time_0() interrupt 1
{
static u16 Smg_count,key_count,i,water_count;
if(++Smg_count>= 2 ) //2ms扫描刷新数码管
{
Smg_count=0;
P2=0xe0;P0=0xff;P2=0x00; //数码管消隐
P2=0xc0;P0=T_COM[i];P2=0x00;
P2=0xe0;P0=~t_display[smg_table[i]];P2=0x00;
i++;
if(i>=8)i=0;
}
if(++key_count>=10){ //10ms扫描独立按键
key_count=0;
key_flag=1;
}
if(mode)
{
if(++water_count>=100) // 0.01L/100ms
{
water_count=0;
water_number++;
if(water_number==9999)
{
P2 = 0xa0;buzzer = 0 ;relay = 0; P2 = 0x00; //继电器断开
mode=0;
}
}
}
else{
water_count=0;
water_price=water_number/2; //水费
}
}
//独立按键的三行代码
void ReadKey()
{
ReadData=P3^0xff;
Trg= ReadData&(ReadData^Cont);
Cont= ReadData;
}
void dsp_key()
{
if(key_flag)
{
key_flag=0;
ReadKey();
switch(Trg)
{
case 0x02: //s6
P2 = 0xa0;buzzer = 0 ;relay = 0; P2 = 0x00; //继电器断开
mode=0;
flag=1; //设置出水量清除标志位
break;
case 0x01: //s7
P2 = 0xa0;buzzer = 0 ;relay = 1; P2 = 0x00; //继电器接通
mode=1;
break;
}
}
}
void main()
{
Close_Peripherals();//关闭外设
Timer0Init(); //定时器初始化
write_adc(0x01);
while(1){
EA=0;
Voltage=read_adc(0x01); //读取光敏电阻的电阻值
EA=1;
if((Voltage*5.0/255)<1.25){ //电阻与电压之间的转换
P2=0x80;P0=0xfe;P2=0x00; //L1亮
}else{
P2=0x80;P0=0xff;P2=0x00; //L1灭
}
dsp_key();
if(mode)
{
if(flag){
flag=0;
water_number=0; //清除出水量
}
//费率0.50
smg_table[0]=16;
smg_table[1]=32;
smg_table[2]=5;
smg_table[3]=0;
//出水量
smg_table[4]=water_number/1000;
smg_table[5]=(water_number%1000/100)+32;
smg_table[6]=water_number%100/10;
smg_table[7]=water_number%10;
}else{
//费率0.50
smg_table[0]=16;
smg_table[1]=32;
smg_table[2]=5;
smg_table[3]=0;
//水费
smg_table[4]=water_price/1000;
smg_table[5]=(water_price%1000/100)+32;
smg_table[6]=water_price%100/10;
smg_table[7]=water_price%10;
}
}
}
2、I2C(AD)
iic.c
#include "iic.h"
#define DELAY_TIME 5
#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1
//总线引脚定义
sbit SDA = P2^1; /* 数据线 */
sbit SCL = P2^0; /* 时钟线 */
void IIC_Delay(unsigned char i)
{
do{_nop_();}
while(i--);
}
//总线启动条件
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 0;
}
//总线停止条件
void IIC_Stop(void)
{
SDA = 0;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 1;
IIC_Delay(DELAY_TIME);
}
//等待应答
bit IIC_WaitAck(void)
{
bit ackbit;
SCL = 1;
IIC_Delay(DELAY_TIME);
ackbit = SDA;
SCL = 0;
IIC_Delay(DELAY_TIME);
return ackbit;
}
//通过I2C总线发送数据
void IIC_SendByte(unsigned char byt)
{
unsigned char i;
for(i=0; i<8; i++)
{
SCL = 0;
IIC_Delay(DELAY_TIME);
if(byt & 0x80) SDA = 1;
else SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 1;
byt <<= 1;
IIC_Delay(DELAY_TIME);
}
SCL = 0;
}
//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
unsigned char i, da;
for(i=0; i<8; i++)
{
SCL = 1;
IIC_Delay(DELAY_TIME);
da <<= 1;
if(SDA) da |= 1;
SCL = 0;
IIC_Delay(DELAY_TIME);
}
return da;
}
void write_adc(unsigned char add)
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_Stop();
}
unsigned char read_adc(unsigned char add)
{
unsigned char temp;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
temp=IIC_RecByte();
IIC_WaitAck();
IIC_Stop();
return temp;
}
iic.h
#include<stc15f2k60s2.h>
#include "intrins.h"
void IIC_Start(void);
void IIC_Stop(void);
bit IIC_WaitAck(void);
void IIC_SendAck(bit ackbit);
void IIC_SendByte(unsigned char byt);
unsigned char IIC_RecByte(void);
void write_adc(unsigned char add);
unsigned char read_adc(unsigned char add);
注:小白而已,写博客只是为了让自己对本次刷题加深印象,同时也希望能对你有一点点帮助!!!
最后
以上就是听话香烟为你收集整理的蓝桥杯------自动售水机的全部内容,希望文章能够帮你解决蓝桥杯------自动售水机所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复