求一个stc89C52单片机与TLC2543连接然后在LCD1602上显示的C语言程序,输入的模拟信号为0~5V电压,谢谢

求一个stc89C52单片机与TLC2543连接然后在LCD1602上显示的C语言程序,输入的模拟信号为0~5V电压,谢谢,第1张

我这里有一个类似的程序:

#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


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12541636.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-26
下一篇 2023-05-26

发表评论

登录后才能评论

评论列表(0条)

保存