蓝桥杯单片机第三届省赛题详细讲解(自动售水机)
蓝桥杯资料包
源码
强烈建议先自己做一遍,这是蓝桥杯单片机最简单的一道题。
首先从试题的系统框图开始看
如图所示,有AD转换,所以IIC肯定是需要用的
有数码管,所以数码管先写上
有按键,但确定是独立按键还是矩阵按键,往下翻
S5,S7所以使用独立按键就行
所以,我们先建立工程,然后把需要的数码管,IIC,独立按键先添加进去并且调试好。
main.c
#include <stc15f2k60s2.h>
#include "intrins.h"
#include "iic.h"#define uchar unsigned char
#define uint unsigned intvoid SMG_output(void);
void init(void);
void Delay1ms(void);
void delay5ms(void);
void Dkey_scan(void);uchar tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,\
0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0xff,0xbf};
uchar SMG[8]={20,20,20,20,20,20,20,20};//初始显示10,全息数码管void main(void)
{init();while(1){SMG_output();Dkey_scan();}
}void Dkey_scan(void) //矩阵按键
{static uchar keybyte=0;static uchar key;if(((P3&0X0F)!=0X0F)&&(keybyte==0)){delay5ms();if((P3&0X0F)!=0X0F){keybyte=1;key=P3&0x0f;}}if((keybyte==1)&&((P3&0X0F)==0X0F)){if((P3&0X0F)==0X0F){switch(key){case 0x0e:SMG[0]=1;break;case 0x0d:SMG[1]=1;break;case 0x0b:SMG[2]=1;break;case 0x07:SMG[3]=1;break;}keybyte=0;}}
}void SMG_output(void) //数码管显示函数
{uchar i;for(i=0;i<8;i++){P2=(P2&0X1F)|0Xc0;P0=(1<<i);P2=(P2&0X1F)|0Xe0;P0=tab[SMG[i]];Delay1ms();}P2=(P2&0X1F)|0Xc0;P0=0Xff;P2=(P2&0X1F)|0Xe0;P0=0Xff;
}void init(void) //初始化函数,关闭所有外设
{P2=(P2&0X1F)|0XA0;P0=0X00;P2=(P2&0X1F)|0X80;P0=0Xff;P2=(P2&0X1F)|0Xc0;P0=0Xff;P2=(P2&0X1F)|0Xe0;P0=0Xff;
}void Delay1ms(void) //@11.0592MHz
{unsigned char i, j;_nop_();_nop_();_nop_();i = 11;j = 190;do{while (--j);} while (--i);
}void delay5ms(void) //@11.0592MHz
{unsigned char i, j;i = 54;j = 199;do{while (--j);} while (--i);
}
iic.c
#include "iic.h"#define DELAY_TIME 40
//IIC的读函数,参数(硬件地址,寄存器地址,数据)
void IIC_write(uchar hw_address,uchar reg_address,uchar num)
{ IIC_Start();IIC_SendByte(hw_address&0xfe);IIC_WaitAck();IIC_SendByte(reg_address);IIC_WaitAck();IIC_SendByte(num);IIC_WaitAck(); IIC_Stop();
}
//IIC读函数 参数:硬件地址,寄存器地址
uchar IIC_read(uchar hw_address,uchar reg_address)
{uchar num;IIC_Start();IIC_SendByte(hw_address&0xfe);IIC_WaitAck();IIC_SendByte(reg_address); IIC_WaitAck();IIC_Stop();IIC_Start();IIC_SendByte(hw_address|0x01);IIC_WaitAck();num=IIC_RecByte();IIC_WaitAck();IIC_Stop(); return num;
}//
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);
}//
void IIC_SendAck(bit ackbit)
{SCL = 0;SDA = ackbit; IIC_Delay(DELAY_TIME);SCL = 1;IIC_Delay(DELAY_TIME);SCL = 0; 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;
}//
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;
}//
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;
}
iic.h
#ifndef _IIC_H
#define _IIC_H#include "stc15f2k60s2.h"
#include "intrins.h"#define uchar unsigned char
#define uint unsigned intsbit SDA = P2^1;
sbit SCL = P2^0;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); uchar IIC_read(uchar hw_address,uchar reg_address);
void IIC_write(uchar hw_address,uchar reg_address,uchar num);#endif
然后编译,会发现有几个警告,*** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS
,像这中警告一般是有函数没有调用,不用理会,直接下载调试。效果应该是按下按键,数码管对应亮一。
然后接着往下看题目。
数码管显示有两种状态,所以肯定是要定义一,个变量用于切换状态的。定义好后,首先按照如图数码管一模一样显示出来,定义一个价格变量price=50,50方便显示
;定义一个总价all_price=50
,然后显示出来。改变之后的代码如下:
uchar SMG_mode=0; //数码管切换状态变量
uchar price=50; //价格变量
uint all_price=50,water_num=100; //总价变量 //出水量定义
void main(void)
{init();while(1){if(SMG_mode==0) //数码管模式一 售水机出水状态数码管显示{//加上10都是为了显示小数点SMG[0]=20;SMG[1]=price/100+10;SMG[2]=price%100/10;SMG[3]=price%10;SMG[4]=water_num/1000;SMG[5]=water_num%1000/100+10;SMG[6]=water_num%100/10;SMG[7]=water_num%10;}else if(SMG_mode==1) //数码管模式二 售水机出停水态数码管显示{//加上10都是为了显示小数点SMG[0]=20;SMG[1]=price/100+10;SMG[2]=price%100/10;SMG[3]=price%10;SMG[4]=all_price/1000;SMG[5]=all_price%1000/100+10;SMG[6]=all_price%100/10;SMG[7]=all_price%10;}SMG_output();Dkey_scan();}
}
如题
然后数码管需要由按键控制,所以在按键中在增加相应控制程序(S7显示数码管模式一,并且继电器接通,L10亮,S6显示数码管模式二,并且继电器断开,L10熄灭),由于只需要S7和S6,所以把独立按键另外两个按键删除。
对应独立按键修改的程序为:
void Dkey_scan(void)
{static uchar keybyte=0;static uchar key;if(((P3&0X0F)!=0X0F)&&(keybyte==0)){delay5ms();if((P3&0X0F)!=0X0F){keybyte=1;key=P3&0x0f;}}if((keybyte==1)&&((P3&0X0F)==0X0F)){if((P3&0X0F)==0X0F){switch(key){case 0x0e:if(SMG_mode==1)SMG_mode=0; //切换数码管模式P2=0XA0;P0=0X10; //点亮L10,接通继电器break;case 0x0d:if(SMG_mode==0)SMG_mode=1;P2=0XA0;P0=0X00; //熄灭L10,关闭继电器break;}keybyte=0;}}
}
记得下载调试!!!
然后接着看试题
由于要使用AD转换,所以要使用IIC了,首先看要求是PCF8591读取光敏电阻的电压,所以IIC读的硬件地址0x90
,然后光敏电阻地址为0x01
,然后输入电压小于1.25V,L1点亮,否则L1熄灭,所以首先要将读取的值转换为电压值,即255转换为5V,然后再进行判断就行。
所以主函数变为:
uchar light=0;
void main(void)
{init();while(1){light=IIC_read(0x90,0x01); //读取光敏电阻阻值light=light*1.9607; //500/255 放大100倍if(light<125) //判断条件{P2=0X80;P0=0XFE; //打开L1;}else if(light>125){P2=0X80;P0=0XFF; //关闭L1;}
然后下载调试,发现遮住光敏电阻L1点亮。
然后再看最后一个要求:
计算价格,并且给出出水量限额,100毫升/秒就是0.1升/秒,所以首先要使用定时器来计时出水。
更改代码如下:
定时器出水
void time0() interrupt 1
{t++;if(t==1000) //1ms计时1000次==1s{t=0;if(SMG_mode==0) //数码管模式0才加水 即出水模式才加水water_num+=10; //每一秒出水}
}
按键计算价格和清零
case 0x0e:if(SMG_mode==1){SMG_mode=0;water_num=0;}//切换数码管模式,出水量清零P2=0XA0;P0=0X10; //点亮L10,接通继电器break;case 0x0d:if(SMG_mode==0)SMG_mode=1;P2=0XA0;P0=0X00; //熄灭L10,关闭继电器all_price=((water_num*price)/100); //计算价格break;
出水限制
if(water_num>9999){SMG_mode=1;P2=0XA0;P0=0X00; //熄灭L10,关闭继电器all_price=((water_num*price)/100); //计算价格}
最后别忘记更改初始出水量和价格,删除没用的函数。
完整代码:
#include <stc15f2k60s2.h>
#include "intrins.h"
#include "iic.h"#define uchar unsigned char
#define uint unsigned intvoid SMG_output(void);
void init(void);
void Delay1ms(void);
void delay5ms(void);
void Dkey_scan(void);
void Timer0Init(void);
uchar tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,\
0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0xff,0xbf};
uchar SMG[8]={20,20,20,20,20,20,20,20};//初始显示10,全息数码管uchar SMG_mode=0; //数码管切换状态变量
uchar price=50; //价格变量
uint all_price=0,water_num=0; //总价变量 //出水量定义
uint light=0;
uint t=0; //定时器变量
void main(void)
{init(); //初始开发板Timer0Init(); //初始化定时器while(1){light=IIC_read(0x90,0x01); //读取光敏电阻阻值light=light*1.9607; //500/255 放大100倍if(light<125) //判断条件{P2=0X80;P0=0XFE; //打开L1;}else if(light>125){P2=0X80;P0=0XFF; //关闭L1;}if(SMG_mode==0) //数码管模式一 售水机出水状态数码管显示{//加上10都是为了显示小数点SMG[0]=20;SMG[1]=price/100+10;SMG[2]=price%100/10;SMG[3]=price%10;SMG[4]=water_num/1000;SMG[5]=water_num%1000/100+10;SMG[6]=water_num%100/10;SMG[7]=water_num%10;}else if(SMG_mode==1) //数码管模式二 售水机出停水态数码管显示{//加上10都是为了显示小数点SMG[0]=20;SMG[1]=price/100+10;SMG[2]=price%100/10;SMG[3]=price%10;SMG[4]=all_price/1000;SMG[5]=all_price%1000/100+10;SMG[6]=all_price%100/10;SMG[7]=all_price%10;}if(water_num>9999){SMG_mode=1;P2=0XA0;P0=0X00; //熄灭L10,关闭继电器all_price=((water_num*price)/100); //计算价格}SMG_output();Dkey_scan();}
}void Dkey_scan(void)
{static uchar keybyte=0;static uchar key;if(((P3&0X0F)!=0X0F)&&(keybyte==0)){delay5ms();if((P3&0X0F)!=0X0F){keybyte=1;key=P3&0x0f;}}if((keybyte==1)&&((P3&0X0F)==0X0F)){if((P3&0X0F)==0X0F){switch(key){case 0x0e:if(SMG_mode==1){SMG_mode=0;water_num=0;}//切换数码管模式,出水量清零P2=0XA0;P0=0X10; //点亮L10,接通继电器break;case 0x0d:if(SMG_mode==0)SMG_mode=1;P2=0XA0;P0=0X00; //熄灭L10,关闭继电器all_price=((water_num*price)/100); //计算价格break;}keybyte=0;}}
}void time0() interrupt 1
{t++;if(t==1000) //1ms计时1000次==1s{t=0;if(SMG_mode==0) //数码管模式0才加水 即出水模式才加水water_num+=10; //每一秒出水}
}void Timer0Init(void) //1毫秒@11.0592MHz
{AUXR |= 0x80; //定时器时钟1T模式TMOD &= 0xF0; //设置定时器模式TL0 = 0xCD; //设置定时初值TH0 = 0xD4; //设置定时初值TF0 = 0; //清除TF0标志TR0 = 1; //定时器0开始计时EA=1;ET0=1; //打开中断
}void SMG_output(void)
{uchar i;for(i=0;i<8;i++){P2=(P2&0X1F)|0Xc0;P0=(1<<i);P2=(P2&0X1F)|0Xe0;P0=tab[SMG[i]];Delay1ms();}P2=(P2&0X1F)|0Xc0;P0=0Xff;P2=(P2&0X1F)|0Xe0;P0=0Xff;
}void init(void)
{P2=(P2&0X1F)|0XA0;P0=0X00;P2=(P2&0X1F)|0X80;P0=0Xff;P2=(P2&0X1F)|0Xc0;P0=0Xff;P2=(P2&0X1F)|0Xe0;P0=0Xff;
}void Delay1ms(void) //@11.0592MHz
{unsigned char i, j;_nop_();_nop_();_nop_();i = 11;j = 190;do{while (--j);} while (--i);
}void delay5ms(void) //@11.0592MHz
{unsigned char i, j;i = 54;j = 199;do{while (--j);} while (--i);
}
最后演示视频
最后可以有问题可以私信和评论。
蓝桥杯单片机第三届省赛题详细讲解(自动售水机)相关推荐
- 蓝桥杯单片机第四届省赛题详细讲解(模拟智能灌溉系统)
看之前强烈建议先自己做一遍!!! 整个工程文件(有注释讲解) 网盘链接 先上演示效果 蓝桥杯单片机第五届模拟智能灌溉系统 首先依旧从赛题的系统框图开始讲起 首先需要做的是将系统框图里的各部分模块提前调 ...
- 蓝桥杯单片机第三届省赛自动售水机
#蓝桥杯单片机省三自动售水机 提示:能力有限仅供参考 本人能力有限仅供新手使用,第一次发表博客难免有错误仅供参考. 提示:以下是本篇文章正文内容,下面案例可供参考 一.main.c 代码如下: #in ...
- 十三届蓝桥杯单片机组省赛真题程序解析
第一次参加蓝桥杯,线上比赛,记录一下 比赛刚开始了十分钟才做上客观题,做上了之后才发现看一次题警告一次,当时就蚌埠住了,随便做了做就交了,手册也没怎么查(查一下直接给了3次黄牌,就没敢查了)其实老师1 ...
- 第jiu届蓝桥杯单片机省赛真题_第九届蓝桥杯单片机组省赛试题.pdf
第九届蓝桥杯单片机组省赛试题 "彩灯控制器"的程序设计与调试 (70 分) 一.基本要求 1.1 使用CT107D 单片机竞赛板,完成"彩灯控制器"功能的程序设 ...
- 蓝桥杯单片机历年初赛真题练习
蓝桥杯单片机历年初赛真题练习第三届-自动售水机 文章目录 蓝桥杯单片机历年初赛真题练习第三届---自动售水机 前言 一.题目要求 二.具体代码 1.驱动部分 2.主程序部分 总结 前言 我参加了第十二 ...
- 2013第四届蓝桥杯Java组省赛题解析
2013第四届蓝桥杯Java组省赛题解析 目录 第一题:高斯日记 第二题:马虎的算式 第三题:第39级台阶 第四题:黄金连分数 第五题:前缀判断 第六题:三部排序 第七题:错误票据 第八题:翻硬币 ...
- 【第十四届蓝桥杯单片机组模拟赛1】
第十四届蓝桥杯单片机组模拟赛1 距第十四届蓝桥杯单片机还有不到一个月的时间啦,加油 源码 /*------------------------------第十四届蓝桥杯单片机模式赛---------- ...
- 蓝桥杯单片机第三届初赛程序设计——“自动售水机”设计任务书
程序设计流程 综述 模板搭建 根据此题要求对模板做出的改变 程序设计 IIC A/D光敏电阻板块程序设计 系统设计 主函数代码 综述 第三届初赛赛题除了基础的独立按键.数码管显示.继电器和蜂鸣器的控制 ...
- 蓝桥杯单片机第七届省赛题详细讲解(模拟风扇控制系统)
看之前强烈建议先自己做一遍!!! 演示视频 题目讲解 完整程序 main.c onewire.h onewire.c 工程文件 演示视频 题目讲解 首先还是从整个赛题的程序框图开始看起,如图. 做题之 ...
最新文章
- WIN7如何替换开机登录画面
- 《Neural networks and deep learning》概览
- linux用户和组帐户管理
- 分酒问题matlab代码,matlab葡萄酒分类数据归一化问题
- Maven 使用 Tomcat7
- 200815-C指针高级和链表
- LLVM完整参考安装
- ROS笔记(31) ArbotiX关节控制器
- 统一异常处理ControllerAdvice
- python模块time_python模块之time和datetime
- 报表服务框架:WEB前端UI
- Office 2007中的config.xml个性定制说明
- rabbitmq启动报错,TCP connection succeeded but Erlang distribution failed
- pythonrender函数_Render函数
- ubuntu 安装eclipes
- HtmlUnit的简单例子
- 远距离蓝牙路由器产品:桂花网Cassia S2000介绍
- 基于微信平台的学生信息管理系统
- 小米机型TWRP_recovery合集分享-支持米9等新机
- AOC AG273QXP 评测
热门文章
- 如何给博客园添加访问统计
- 北、上、深交易所分别发布北交所上市公司转板办法,北交所上市公司87家
- SSM毕设项目羽毛球场预约系统axx7m(java+VUE+Mybatis+Maven+Mysql)
- gvim c语言,gvim+tdm-gcc设置c语言编译环境
- 西安全国计算机等级考试,全国计算机等级考试 西安电子.pdf
- oracle ebs ar 表,Oracle EBS R12 常用表表结构总结之AR应收模块
- Python图像处理库PIL中的convert函数的用法
- PythonOCC基础使用:建模——基础三维实体(球体,长方体,棱柱/台/锥,圆柱/锥/台,环形)
- LTE MAC2 SR-BSR
- 哪个专业就业前景最好?