#include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include <intrins.h>//衫耐包含NOP空指令函数_nop_()
#include<LCD1602.h>
#define AddWr 0x90 //写数据地址
#define AddRd 0x91 //读数据地址
sbit RST=P2^4 //时钟 加上巧森后可以关掉DS1302芯片输出
sbit Sda=P2^0 //定义总线连接端口
sbit Scl=P2^1
sbit dula=P2^6
sbit wela=P2^7
bit ADFlag //定义AD采样标志位
unsigned char code Datatab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}//7段数共阴码孝塌亩管段码表
data unsigned char Display[8]//定义临时存放数码管数值
/*------------------------------------------------
延时程序
------------------------------------------------*/
void mDelay(unsigned char j)
{
unsigned int i
for(j>0j--)
{
for(i=0i<125i++)
{}
}
}
/*------------------------------------------------
初始化定时器1
------------------------------------------------*/
void Init_Timer1(void)
{
TMOD |= 0x10
TH1=0xff /* Init value */
TL1=0x00
//PT1=1 /* 优先级*/
EA=1 /* interupt enable */
ET1=1/* enable timer1 interrupt */
TR1=1
}
/*------------------------------------------------
启动IIC总线
------------------------------------------------*/
void Start(void)
{
Sda=1
_nop_()
Scl=1
_nop_()
Sda=0
_nop_()
Scl=0
}
/*------------------------------------------------
停止IIC总线
------------------------------------------------*/
void Stop(void)
{
Sda=0
_nop_()
Scl=1
_nop_()
Sda=1
_nop_()
Scl=0
}
/*------------------------------------------------
应答IIC总线
------------------------------------------------*/
void Ack(void)
{
Sda=0
_nop_()
Scl=1
_nop_()
Scl=0
_nop_()
}
/*------------------------------------------------
非应答IIC总线
------------------------------------------------*/
void NoAck(void)
{
Sda=1
_nop_()
Scl=1
_nop_()
Scl=0
_nop_()
}
/*------------------------------------------------
发送一个字节
------------------------------------------------*/
void Send(unsigned char Data)
{
unsigned char BitCounter=8
unsigned char temp
do
{
temp=Data
Scl=0
_nop_()
if((temp&0x80)==0x80)
Sda=1
else
Sda=0
Scl=1
temp=Data<<1
Data=temp
BitCounter--
}
while(BitCounter)
Scl=0
}
/*------------------------------------------------
读入一个字节并返回
------------------------------------------------*/
unsigned char Read(void)
{
unsigned char temp=0
unsigned char temp1=0
unsigned char BitCounter=8
Sda=1
do
{
Scl=0
_nop_()
Scl=1
_nop_()
if(Sda)
temp=temp|0x01
else
temp=temp&0xfe
if(BitCounter-1)
{
temp1=temp<<1
temp=temp1
}
BitCounter--
}
while(BitCounter)
return(temp)
}
/*------------------------------------------------
写入DA数模转换值
------------------------------------------------*/
void DAC(unsigned char Data)
{
Start()
Send(AddWr)//写入芯片地址
Ack()
Send(0x40) //写入控制位,使能DAC输出
Ack()
Send(Data) //写数据
Ack()
Stop()
}
/*------------------------------------------------
读取AD模数转换的值,有返回值
------------------------------------------------*/
unsigned char ReadADC(unsigned char Chl)
{
unsigned char Data
Start() //写入芯片地址
Send(AddWr)
Ack()
Send(0x40|Chl)//写入选择的通道,本程序只用单端输入,差分部分需要自行添加
//Chl的值分别为0、1、2、3,分别代表1-4通道
Ack()
Start()
Send(AddRd) //读入地址
Ack()
Data=Read() //读数据
Scl=0
NoAck()
Stop()
return Data //返回值
}
void cmg(void)//数码管锁存函数 关时钟DS1302
{
dula=1
P0=0x00
dula=0
wela=1
P0=0x00
wela=0
RST=0 // 关时钟DS1302
}
/*------------------------------------------------
主程序
------------------------------------------------*/
void main()
{
unsigned char num //DA数模输出变量
unsigned char ADtemp //定义中间变量
InitLcd()
mDelay(20)
Init_Timer1()
cmg() //数码管锁存
while(1)
{
DAC(num) //DA输出,可以用LED模拟电压变化
num++ //累加,到256后溢出变为0,往复循环。显示在LED上亮度逐渐变化
mDelay(20)//延时用于清晰看出变化
if(ADFlag) //定时采集输入模拟量
{
ADFlag=0
ADtemp=ReadADC(0)
TempData[0]=(ReadADC(0))/50//处理0通道电压显示
TempData[1]=((ReadADC(0))%50)/10
ADtemp=ReadADC(1)
TempData[2]=(ReadADC(1))/50//处理1通道电压显示 此通道暂时屏蔽,可以自行添加
TempData[3]=((ReadADC(1))%50)/10
ADtemp=ReadADC(2)
TempData[4]=(ReadADC(2))/50//处理1通道电压显示 此通道暂时屏蔽,可以自行添加
TempData[5]=((ReadADC(2))%50)/10
ADtemp=ReadADC(3)
TempData[6]=(ReadADC(3))/50//处理1通道电压显示 此通道暂时屏蔽,可以自行添加
TempData[7]=((ReadADC(4))%50)/10
disp()
}
}
}
/*------------------------------------------------
定时器中断程序
------------------------------------------------*/
void Timer1_isr(void) interrupt 3 using 1//定时器1执行数码管动态扫描
{
static unsigned int j
TH1=0xfb //重新赋值
TL1=0x00
j++
if(j==200)
{j=0ADFlag=1} //定时置位AD采样标志位
// P0=Display[count]//用于动态扫描数码管
// P2=count
// count++
// if(count==8) //表示扫描8个数码管
// count=0
}
#include <reg52.h> //调用单片机头文件#define uchar unsigned char //尺渗无符号字符型 宏定义 变量范围0~255
#define uint unsigned int //无符号整型 宏定义 变量范围0~65535
#include "lcd1602.h"
#include "iic.h"
uchar value,i //变量
uchar flag_lj_en //边加
uchar flag_lj_en_value
sbit relay = P2^2 //继电器定义
sbit beep = P3^3 //蜂鸣器定义
sbit beiguan = P2^3 //背光
uint flag_time
uint flag_guan
uchar smg_i
uchar dis_smg[7]={0}
uchar password[7]={6,5,4,3,2,1} //密码保存
uchar password_bj[7]={1,2,3,4,5,6} //密码比较
uchar code password_r[6] = {1,2,3,1,2,3}
uchar code password_gl[6] = {5,2,0,0,2,5}
uchar password_xg[6] //密码修改
uchar flag_password //密码正确否
uchar flag_password_cichu1//密码错误次数
bit flag_200ms=1//200ms标志位
uchar key_can
uchar menu_1,menu_i
#include "iic.h"
/***********************1ms延时函数*****************************/
void delay_1ms(uint q)
{
uint i,j
for(i=0i<qi++)
for(j=0j<120j++)
}
void key() //独立按键程序
{
static uchar key_new = 0, key_l
key_can = 20 //按答悔键值还原
P1 = 0x0f
if((P1 &0x0f) != 0x0f) //按键按下
{
delay_1ms(1) //按键消抖动
if(((P1 &0x0f) != 0x0f) &&(key_new == 1))
{ //确认是按键按下
key_new = 0
key_l = (P1 | 0xf0) //矩阵键盘扫描
P1 = key_l
switch(P1)
{
case 0xee: key_can = 1 break //得到按键值
case 0xde: key_can = 4 break //得到按键值
case 0xbe: key_can = 7 break //得到按键值
case 0x7e: key_can = 10 break //得到按键值
case 0xed: key_can = 0 break //得到按键值
case 0xdd: key_can = 8 break //得到按键值
case 0xbd: key_can = 5 break //得到按键值
case 0x7d: key_can = 2 break //得到按键值
case 0xeb: key_can = 3 break //得到按键值
case 0xdb: key_can = 6 break //得到按键值
case 0xbb: key_can = 9 break //得到按键陵举脊值
case 0x7b: key_can = 11 break //得到按键值
case 0xe7: key_can = 15 break //得到按键值
case 0xd7: key_can = 14 break //得到按键值
case 0xb7: key_can = 13 break //得到按键值
case 0x77: key_can = 12 break //得到按键值
}
}
}
else
{
key_new = 1
flag_lj_en = 0
}
}
/*****************密码还原********************/
void password_return()
{
if(flag_lj_en == 1)
{
flag_lj_en_value ++
if(flag_lj_en_value >13) //按下3秒钟就自动密码还原
{
flag_lj_en_value = 0
flag_lj_en = 0
write_24c02_8(6,0,password_r)
beep = 0
delay_1ms(500)
beep = 1
read_24c02_8(6,0,password)
}
}
}
/***************把数组清空**********************/
void clear_shuzu(uchar *p)
{
for(i=0i<7i++)
p[i] = 0
}
/*************定时器0初始化程序***************/
void time_init()
{
EA = 1 //开总中断
TMOD = 0X01 //定时器0、工作方式1
ET0 = 1 //开定时器0中断
TR0 = 1 //允许定时器0定时
}
/******************下载程序密码初始化**********************/
void password_chushifa()
{
scl = 0
value = read_24c02(10)
if(value != 75)
{
value = 75
beep = 0
write_24c02(10,value)
delay_1ms(200)
write_24c02_8(6,0,password_r)
delay_1ms(200)
read_24c02_8(6,0,password)
beep = 1
}
}
/****************按键功能处理********************/
void key_with()
{
static uchar value
if(key_can == 14) //手动关闭密码锁
relay = 1
if(key_can == 10) //用做密码从新回到初始值
{
flag_lj_en = 1 //连加使能
flag_lj_en_value = 0
}
if(menu_1 == 0)
{
if(key_can <= 9)
if(menu_i <6) //密码输入
{
menu_i ++
if(menu_i >6)
menu_i = 6
smg_i = menu_i
for(i=6i>0i--)
password_bj[i] = password_bj[i-1]
password_bj[0] = key_can
for(i=0i<smg_ii++)
dis_smg[i] ='*'//0x30 + password_bj[i]
write_string(2,7,dis_smg)
lcd1602_guanbiao(1,7 + menu_i + 0x40) //开光标
}
if(key_can == 11) //密码删除
{
for(i=0i<menu_ii++)
password_bj[i] = password_bj[i+1]
menu_i --
password_bj[menu_i] = ' '
dis_smg[menu_i] = ' '
write_string(2,7,dis_smg)
lcd1602_guanbiao(1,7 + menu_i + 0x40) //开光标
}
if(key_can == 15) //确认键
{
value = 0
for(i=0i<6i++)
{
if(password_bj[i] == password_gl[i]) //判断管理员密码
{
value ++
if(value >= 6) //密码正确
{
write_string(2,0,"return ")
beep = 0
delay_1ms(200)
read_24c02_8(6,0,password)
beep = 1
delay_1ms(2000)
}
}
}
if(value <6)
for(i=0i<6i++)
{
if(password_bj[i] == password[i])
{
flag_password = 1 //密码正确
relay = 0//打开密码锁
for(i=0i<6i++)
dis_smg[i] = 0xbf
}
else
{
flag_password = 0
flag_password_cichu1 ++
write_string(1,0," Password error ")
write_string(2,0," cishu: ")
write_sfm2(2,9,flag_password_cichu1)
delay_1ms(280)
for(i=0i<6i++)
{
beep = ~beep
delay_1ms(200)
}
beep = 1
delay_1ms(800)
break //密码不正确
}
}
clear_shuzu(dis_smg)
write_string(1,0," Password Lock ")
write_string(2,0," Input: ")
lcd1602_guanbiao(1,7+0x40) //开光标
menu_i = 0
}
}
}
/****************修改密码********************/
void xiugai_password()
{
if(key_can == 13) //修改密码
{
if((relay == 0) &&(menu_1 == 0))
{
menu_1 = 1 menu_i = 0
clear_shuzu(password_bj) //数据清空
clear_shuzu(dis_smg)
write_string(1,0,"Input1: ")
write_string(2,0,"Input2: ")
lcd1602_guanbiao(1,7) //开光标
}
}
if(menu_1 == 1) //第一次输入修改的密码
{
if(key_can <= 9)
{
if(menu_i <6)
{
menu_i ++
if(menu_i >6)
menu_i = 6
smg_i = menu_i
for(i=7i>0i--)
password_bj[i] = password_bj[i-1]
password_bj[0] = key_can
for(i=0i<menu_ii++)
dis_smg[i] ='*'
write_string(1,7,dis_smg)
lcd1602_guanbiao(1,7 + menu_i) //开光标
}
}
if(key_can == 11) //删除键
{
for(i=0i<menu_ii++)
password_bj[i] = password_bj[i+1]
menu_i --
password_bj[menu_i] = ' '
dis_smg[menu_i] = ' '
write_string(1,7,dis_smg)
lcd1602_guanbiao(1,7 + menu_i) //开光标
}
if(key_can == 15) //确定键
{
clear_shuzu(password_xg)
clear_shuzu(dis_smg)
lcd1602_guanbiao(1,8 + 0x40) //开光标
menu_1 = 2
menu_i = 0
key_can = 20
}
}
if(menu_1 == 2) //第二次输入修改的密码
{
if(key_can <= 9)
{
if(menu_i <6)
{
menu_i ++
if(menu_i >6)
menu_i = 6
for(i=5i>0i--)
password_xg[i] = password_xg[i-1]
password_xg[0] = key_can
for(i=0i<menu_ii++)
dis_smg[i] ='*'//0x30 + password_xg[i]
write_string(2,7,dis_smg)
lcd1602_guanbiao(1,7 + menu_i + 0x40) //开光标
}
}
if(key_can == 11) //删除键
{
for(i=0i<menu_ii++)
password_xg[i] = password_xg[i+1]
password_xg[menu_i] = ' '
dis_smg[menu_i] = ' '
write_string(2,7,dis_smg)
lcd1602_guanbiao(1,7 + menu_i + 0x40) //开光标
}
if(key_can == 15) //确定键
{
for(i=0i<6i++)
{
if(password_bj[i] == password_xg[i])
{
flag_password = 1 //两次输入的密码一样
}
else
{
flag_password = 0
write_string(1,0," Password Error ")
write_string(2,0," reenter")
delay_1ms(300)
for(i=0i<6i++)
{
beep = ~beep //提示三声
delay_1ms(300)
}
beep = 1
delay_1ms(1000)
break //密码不正确
}
}
if(flag_password == 1) //两次输入的密码一样的
{
for(i=0i<6i++)
{
write_string(1,0,"Password")
write_string(2,0,"Succeed ")
password[i] = password_bj[i] //保存密码
}
write_24c02_8(6,0,password)
delay_1ms(300)
beep = 0
delay_1ms(2000)
beep = 1
}
clear_shuzu(password_xg)
clear_shuzu(dis_smg)
write_string(1,0," Password Lock ")
write_string(2,0," Input: ")
lcd1602_guanbiao(1,7+0x40) //开光标
menu_1 = 0
menu_i = 0
}
}
}
/******************主程序**********************/
void main()
{
static uint value
password_chushifa()
time_init() //定时器初始化
read_24c02_8(6,0,password)
init_1602()
beiguan = 0
while(1)
{
if(flag_password_cichu1 <3) //错误三次按键不能用了
{
key() //按键函数
if(key_can <20)
{
if(beiguan == 0)
{
if(menu_1 == 0)
key_with() //按键处理函数
xiugai_password() //修改密码
}
else
beiguan = 0
flag_time = 0
}
}
if(flag_200ms == 1)
{
flag_200ms = 0
if(beiguan == 0) //延时关闭锁20秒关闭背光
{
flag_time ++
// write_sfm2(2,10,flag_time)
if(flag_time >= 5 * 30) //30秒
{
flag_time = 0
beiguan = 1 //关闭背光
}
}
if(relay == 0) //延时关闭锁
{
flag_guan++
if(flag_guan >= 5 * 10) //10秒
{
flag_guan = 0
relay = 1 //关闭密码锁
}
}else
flag_guan = 0
if(flag_password_cichu1 >= 3)
{
value ++ //200ms
beep = ~beep //蜂鸣器报警
if(value >= 5 * 60) //1分钟
{
value = 0
beep = 1
flag_password_cichu1 = 0
}
}
password_return() //密码还原
}
delay_1ms(1)
}
}
/*************定时器0中断服务程序***************/
void time0_int() interrupt 1
{
static uchar value
TH0 = 0x3c
TL0 = 0xb0// 50ms 12M
value ++
if(value % 4 == 0)
{
flag_200ms = 1
}
}
#ifndef _IIC_H_
#define _IIC_H_
sbit scl = P2^1
sbit sda = P2^0
/***************启始信号 ***************************/
void start()
{
sda = 1
scl = 1
sda = 0
scl = 0
}
/****************结束信号 **************************/
void stop()
{
sda = 0
scl = 1
sda = 1
scl = 0
}
/*****************检测应答*************************/
void ack()
{
uchar i
sda = 1
scl = 1
while((i <100) &(sda == 1)) i++
scl =0
}
void ack_zhuji()
{
sda = 0
scl = 1
scl = 0
sda = 1
}
/*****************非应答*************************/
void no_ack()
{
sda = 1
scl = 1
scl = 0
}
/*****************写一个字节*************************/
void write_iic(uchar dat)
{
uchar i
for(i=0i<8i++)
{
scl = 0
dat <<= 1
sda = CY
scl = 1
}
scl = 0
}
/*******************读一个字节***********************/
uchar read_iic()
{
uchar i,value
for(i=0i<8i++)
{
scl = 1
value <<= 1
if(sda == 1)
value |= 0x01
scl = 0
}
return value
}
/*****************向24C02写一个字节进去*************************/
void write_24c02(uchar add,uchar dat)
{
start()
write_iic(0xa0)
ack()
write_iic(add)
ack()
write_iic(dat)
no_ack()
stop()
}
/******************从24C02读一个字节进去************************/
uchar read_24c02(uchar add)
{
uchar value
start()
write_iic(0xa0)
ack()
write_iic(add)
ack()
start()
write_iic(0xa1)
ack()
value = read_iic()
no_ack()
stop()
return value
}
void write_24c02_8(uchar n,uchar add,uchar *p)
{
uchar i
EA = 0
start()
write_iic(0xa0)
ack()
write_iic(add)
for(i=0i<ni++)
{
ack()
write_iic(*p)
p++
}
no_ack()
stop()
EA = 1
}
void read_24c02_8(uchar n,uchar add,uchar *p)
{
uchar i
EA = 0
start()
write_iic(0xa0)
ack()
write_iic(add)
ack()
start()
write_iic(0xa1)
ack()
for(i=0i<ni++)
{
p[i] = read_iic()
if(i == n-1)
{
ack()
stop()
}
else
ack_zhuji()
}
EA = 1
}
#endif
显示器程序贴不下了
原来的1602是这样的:
连接到Arduino上需要接好多线,于是买了块IIC的板子改成IIC接口,就是这货:
由于Arduino的I/O口数量有限,如果直接用Arduino的I/O口直接驱动LCD1602/2004这样会占用较多的I/O口资源也不利于连接更多的其他设备。IIC LCD1602/2004转接板可以大大减少需要使用IO接口,原来的1602/2004屏需要7(RS、RW、E、D4~D7)个IO口才能驱动起来,而这个模块可以省去5个IO口。
模块采用PCF8574,它通过两条双向总线(I2C)可使大多数 MCU 实现远程 I/O口扩展。该器件包含一个 8 位准双向口和一个I2C总线接口。PCF8574 电流消耗很低,且口输出锁存具有大电流驱动能力,可直接驱动 LED。它还带有一条中断接线(INT开漏输出)可与 MCU 的中断逻辑相连。通过 INT 发送中断信号, 远端 I/O 口不必经过 I2C 总线通信就可通知 MCU 是否有数据从端口输入。
但是这块板子也是插针,要想连接1602的化,需要通过面包板才行,这桐橡个不能忍,于是开始拆拆拆。
将原1602的排针拆除,直接焊接IIC转接板。说起来简单,实际 *** 作时发现拆除排针还念带是需要一定的技术的,最局高旁终拆的一团糟,一度以为板子拆坏了。
焊上转接板发现只有背光灯是亮的,查了半天发现是对比度的问题
使用小螺丝刀调节该电位器,从而调节对比度,1602显示屏显示。
大功告成,焊工依然很烂!
PS:
I2C github库
https://github.com/marcoschwartz/LiquidCrystal_I2C
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)