2019年3月14日更新
越是简单的题也是容易出错!
审题错误:
1、题目要求读取光敏电阻电压值,应该读取PCF8591的AIN1数据,而我写的是读取RB2也就是AIN3的数据
2、题目要求出水量100ml/s,我写成了1L/s,更改定时器中断中数据
这个题的编程部分,,,是真的简单!!!
这个题真的没什么好说的,就一个AD和最基础的数码管显示,按键控制。
main.c
#include
#include "sys.h"
bit mode = 0;
bit flag_100ms = 0;
u8 price = 50; //price 0.5元/L 价格和全部需要*100
u16 volume = 0, money = 0;
void main(void)
{
u16 val;
All_Init();
Timer0Init();
EA = 1;
while(1)
{
//读取AD值控制LED程序
if(flag_100ms)
{
flag_100ms = 0;
val = Read_AIN(0x01); //2019.3.14更新,更改为读取AIN1数据
if(val < 125)
Led_illume(0xfe);
else
Led_illume(0xff);
}
Key_press();
Nixie_Show();
}
}
sys.c
#include "sys.h"
void All_Init(void)
{
P2 = (P2 & 0x1f) | 0x80; //打开Y4C(LED)
P0 = 0xff; //关闭LED
P2 = (P2 & 0x1f) | 0xe0; //打开Y7C(数码管)
P0 = 0xff; //关闭数码管
P2 = (P2 & 0x1f) | 0xa0; //打开Y5C
P0 = 0x00; //关闭蜂鸣器、继电器
P2 = P2 & 0x1f; //关闭所有使能
}
void Timer0Init(void) //2毫秒@11.0592MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x9A; //设置定时初值
TH0 = 0xA9; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1;
}
void Timer0(void) interrupt 1
{
static u8 T0count1 = 0, T0count2 = 0;
//控制接水程序
if(mode == 1)
{
T0count1 ++;
if(T0count1 >= 50) //2019.3.14更新,原本是5改为现在的50,
{
T0count1 = 0;
volume ++;
}
}
//100ms计时控制程序
T0count2 ++;
if(T0count2 >= 50)
{
T0count2 = 0;
flag_100ms = 1;
}
//继电器控制程序
if(mode == 1)
{
if(volume < 9999)
{
P0 = 0x00;
P2 = (P2 & 0x1f) | 0xa0; //打开Y5C
P04 = 1;
P2 = P2 & 0x1f; //关闭所有使能
}
else if(volume >= 9999)
{
mode = 0;
money = volume / 2;
volume = 0;
}
}
else
{
P0 = 0x00;
P2 = (P2 & 0x1f) | 0xa0; //打开Y5C
P04 = 0;
P2 = P2 & 0x1f; //关闭所有使能
}
Key_Scan();
Nixie_Scan();
}
sys.h
#ifndef _SYS_H_
#define _SYS_H_
typedef unsigned char u8;
typedef unsigned int u16;
typedef unsigned long u32;
#include
#include
#include "iic.h"
extern bit mode;
extern bit flag_100ms;
extern u8 price;
extern u16 money, volume;
void All_Init(void);
void Timer0Init(void);
void Key_Scan(void);
void Key_drive(u8 key);
void Key_press(void);
void Nixie_Scan(void);
void Nixie_Show(void);
void Led_illume(u8 dat);
#endif
display.c
#include "sys.h"
u8 code Nixie[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8,
0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e,
0xff, 0xbf}; //共阳数码管码字
u8 NixieBuff[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; //数码管显示缓冲区,初值0xff确保启动时都不亮
u8 smg1,smg2,smg3,smg4,smg5,smg6,smg7,smg8;
//数码管显示
void Nixie_Scan(void)
{
static u8 index = 0;
P2 = (P2 & 0x1f) | 0xe0; //数码管消隐
P0 =0xff;
P2 = (P2 & 0x1f) | 0xc0; //数码管片选
P0 = 0x01 << index;
P2 = (P2 & 0x1f) | 0xe0; //数码管段选
P0 = NixieBuff[index];
P2 &= 0x1f;
index ++;
index &= 0x07;
}
//数码管显示
void Nixie_Show(void)
{
if(mode == 0)
{
smg1 = 16;
smg2 = price / 100;
smg3 = (price % 100) / 10;
smg4 = price % 10;
smg5 = money / 1000;
smg6 = (money % 1000) / 100;
smg7 = (money % 100) / 10;
smg8 = money % 10;
}
else if(mode == 1)
{
smg1 = 16;
smg2 = price / 100;
smg3 = (price % 100) / 10;
smg4 = price % 10;
smg5 = volume / 1000;
smg6 = (volume % 1000) / 100;
smg7 = (volume % 100) / 10;
smg8 = volume % 10;
}
NixieBuff[0] = Nixie[smg1];
NixieBuff[1] = Nixie[smg2] & 0x7f;
NixieBuff[2] = Nixie[smg3];
NixieBuff[3] = Nixie[smg4];
NixieBuff[4] = Nixie[smg5];
NixieBuff[5] = Nixie[smg6] & 0x7f;
NixieBuff[6] = Nixie[smg7];
NixieBuff[7] = Nixie[smg8];
}
void Led_illume(u8 dat)
{
P0 = 0xff;
P2 = (P2 & 0x1f) | 0x80; //打开Y4C(LED)
P0 = dat; //点亮LED
P2 = P2 & 0x1f;
}
key.c
#include "sys.h"
u8 KeySta[] = {1, 1, 1, 1}; //键值存储区
u8 Keybackup[] = {1, 1, 1, 1}; //键值备份区
sbit S4 = P3^3;
sbit S5 = P3^2;
sbit S6 = P3^1;
sbit S7 = P3^0;
//按键扫描函数,在定时器中断里调用
void Key_Scan(void)
{
static u8 Keybuff[] = {0xff, 0xff, 0xff, 0xff}; //按键缓冲区
u8 i = 0;
Keybuff[0] = (Keybuff[0] << 1) | S7;
Keybuff[1] = (Keybuff[1] << 1) | S6;
Keybuff[2] = (Keybuff[2] << 1) | S5;
Keybuff[3] = (Keybuff[3] << 1) | S4;
for(i = 0; i < 4; i++)
{
if(Keybuff[i] == 0xff) //按键松开
KeySta[i] = 1;
else if(Keybuff[i] == 0x00) //按键按下
KeySta[i] = 0;
else //键值不稳定
{}
}
}
void Key_drive(u8 key)
{
if(key == 0) //S7 开始接水
mode = 1;
else if((key == 1) && (mode == 1)) //S6 停止接水
{
mode = 0;
money = volume / 2;
volume = 0;
}
}
//检测按键是否按下,在main函数调用
void Key_press(void)
{
u8 i;
for(i = 0; i < 4; i ++)
{
if(KeySta[i] != Keybackup[i])
{
if(Keybackup[i] != 0) //按键松开时操作
Key_drive(i);
Keybackup[i] = KeySta[i];
}
}
}
iic.c
#include "sys.h"
#define somenop {_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();}
//总线引脚定义
sbit SDA = P2^1; /* 数据线 */
sbit SCL = P2^0; /* 时钟线 */
//总线启动条件
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
somenop;
SDA = 0;
somenop;
SCL = 0;
}
//总线停止条件
void IIC_Stop(void)
{
SDA = 0;
SCL = 1;
somenop;
SDA = 1;
}
//应答位控制
void IIC_Ack(bit ackbit)
{
if(ackbit)
{
SDA = 0;
}
else
{
SDA = 1;
}
somenop;
SCL = 1;
somenop;
SCL = 0;
SDA = 1;
somenop;
}
//等待应答
bit IIC_WaitAck(void)
{
SDA = 1;
somenop;
SCL = 1;
somenop;
if(SDA)
{
SCL = 0;
IIC_Stop();
return 0;
}
else
{
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;
}
somenop;
SCL = 1;
byt <<= 1;
somenop;
SCL = 0;
}
}
//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
unsigned char da;
unsigned char i;
for(i=0;i<8;i++)
{
SCL = 1;
somenop;
da <<= 1;
if(SDA)
da |= 0x01;
SCL = 0;
somenop;
}
return da;
}
unsigned char Read_AIN(unsigned char chn)
{
unsigned char dat;
unsigned int val;
EA = 0;
IIC_Start(); //IIC总线起始信号
IIC_SendByte(0x90); //PCF8591的写设备地址
IIC_WaitAck(); //等待从机应答
IIC_SendByte(chn); //写入PCF8591的控制字节
IIC_WaitAck(); //等待从机应答
IIC_Stop(); //IIC总线停止信号
IIC_Start(); //IIC总线起始信号
IIC_SendByte(0x91); //PCF8591的读设备地址
IIC_WaitAck(); //等待从机应答
dat = IIC_RecByte(); //读取PCF8591通道3的数据
IIC_Ack(0); //产生非应答信号
IIC_Stop(); //IIC总线停止信号
val = (dat * 500) / 255;
EA = 1;
return val;
}
iic.h
#ifndef _IIC_H
#define _IIC_H
//函数声明
void IIC_Start(void);
void IIC_Stop(void);
void IIC_Ack(bit ackbit);
void IIC_SendByte(unsigned char byt);
bit IIC_WaitAck(void);
unsigned char IIC_RecByte(void);
unsigned char Read_AIN(unsigned char chn);
#endif