CH451和单片机数码管显示程序(循环右移)

CH451和单片机数码管显示程序(循环右移),第1张

数码管循环右移#include<reg52.h>//包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义

#define DataPort P0 //定义数据端口 程序中遇到DataPort 则用P0 替换

sbit LATCH1=P2^6//定义锁存使能端口 段锁存

sbit LATCH2=P2^7// 位锁存

unsigned char code DuanMa[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8}

// 显示段码值01234567

unsigned char code WeiMa[]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01}

//分别对应相应的数码管点亮,即位码

void Delay(unsigned int t)//函数声明

/*------------------------------------------------

主函数

------------------------------------------------*/

main()

{

unsigned char i=0

while(1)

{

DataPort=WeiMa[i]//取位码

LATCH2=1//位锁存

LATCH2=0

DataPort=DuanMa[i]//取显示数据,段码

LATCH1=1//段锁存

LATCH1=0

Delay(200)//扫描间隙延时,时间太长会闪烁,太短会造成重影

i++

if(8==i)//检测8位扫描完全结束?如扫描完成则从第一个开始再次扫描8位

i=0

}

}

/*------------------------------------------------

延时函数,含有输入参数 unsigned int t,无返回值

unsigned int 是定义无符号整形变量,其值的范围是

0~65535

------------------------------------------------*/

void Delay(unsigned int t)

{

while(--t)

}

译码指的是不转成BCD码,也就是说如果连接是按顺序连接数码管的八个管脚,在对CH451初始化后,可发送设置,让它用译码方式,(默认不译码),译码后,有个表,发送数据是多少显多少。不译码,需要在程序中写个表,手工译码,也就是数码管的a、b、c...对应的灯亮,总体显一个数。

4线串行接口,是和单片机的通信采用串行通信,其中一次传输4个数据,通过CLOCK管教控制,具体请看CH451手册

下面是一段CH451用汇编编写的驱动程序,望对理解有帮助

****************************************************************************

需要主程序定义的参数

CH451_DCLKBIT P3.4 串行数据时钟,上升沿激活

CH451_DIN BIT P3.3 串行数据输出,接 CH451 的数据输入

CH451_LOADBIT P2.3 串行命令加载,上升沿激活

CH451_DOUTBIT P2.2 INT0,键盘中断和键值数据输入,接 CH451 的数据输出

CH451_KEY DATA 7FH 存放键盘中断中读取的键值

****************************************************************************

R452 367 1

ORG 0000H

START:

ACALL CH451_INIT 调用初始化程序

MOV R5,#10H 将要显示的数放入R5中

MOV R4,#04H 将要在第几位上显示放在R4中,最右边是0位

KEYSHOW:

ACALL SCAN1

ACALL CHANGE

SJMP KEYSHOW

SJMP $

****************************************************************************

子程序调用

****************************************************************************

初始化子程序

CH451_INIT:

CLR CH451_DIN先低后高,输出上升沿通知 CH451 选择 4 线串行接口

SETB CH451_DCLK 置为默认的高电平

SETB CH451_DIN

SETB CH451_LOAD

SETB CH451_DOUT 置为输入

CLR IT0 置外部信号为低电平触发

SETB PX0 置高优先级或者低优先级

CLR IE0 清中断标志

SETB EX0 允许键盘中断

MOV B,#04H 设置为键盘与显示开

MOV A,#03H

ACALL CH451_WRITE

RET

****************************************************************************

数码管显示程序

****************************************************************************

转换程序,在R4位显示R5值

CHANGE:

MOV A,R5

ACALL TTA 对应M2t1板的数码管转换

MOV R2,A

MOV A,R4

ACALL TTB 对应m2t1板的数码管位置转换

MOV B,A

MOV A,R2

ACALL CH451_WRITE

RET

M2T1板数码管对应表

TTA: MOV DPTR,#TAB_A

MOVC A,@A+DPTR

RET

对应m2t1板的数码管位置转换

TTB: MOV DPTR,#TAB_B

MOVC A,@A+DPTR

RET

TAB_A:

DB 0BEH0 显示数

DB 24H 1

DB 0EAH2

DB 0E6H3

DB 74H 4

DB 0D6H5

DB 0DEH6

DB 0A4H7

DB 0FEH8

DB 0F6H9

DB 0FCHA

DB 5EH B

DB 4AH C

DB 0BEHD

DB 0DAHE

DB 0E4HF

DB 00H 10H无显示

DB 0FEH11H对于数码管0位倒过来焊接的人,可以显示°C

DB 40H 12H - 号

TAB_B:

DB 0AH0 显示数码管号

DB 09H1

DB 0BH2

DB 08H3

DB 0CH4

DB 0DH5

DB 0EH6

DB 0FH7

****************************************************************************

键盘扫描程序

****************************************************************************

SCAN1:MOV C,CH451_DOUT

JC SCAN1

ACALL CH451_READ

MOV R1,A

C0: CJNE A,#40H,C1

MOV R5,#00H

AJMP TES

C1: CJNE A,#43H,C2

MOV R5,#01H

AJMP TES

C2: CJNE A,#41H,C3

MOV R5,#02H

AJMP TES

C3: CJNE A,#42H,C4

MOV R5,#03H

AJMP TES

C4: CJNE A,#48H,C5

MOV R5,#04H

AJMP TES

C5: CJNE A,#4BH,C6

MOV R5,#05H

AJMP TES

C6: CJNE A,#49H,C7

MOV R5,#06H

AJMP TES

C7: CJNE A,#4AH,SCAN1

MOV R5,#07H

AJMP TES

TES:

RET

****************************************************************************

移位程序

****************************************************************************

DELAY_1S 延迟1秒

DELAY_1S:

MOV R7,#20

DEL1:MOV R6,#200

DEL2:MOV R3,#248

DJNZ R3,$

DJNZ R6,DEL2

DJNZ R7,DEL1

RET

左四位左移位

/*LIFT:

MOV B,#03H

MOV A,#00H

ACALL CH451_WRITE

INC R5

ACALL CHANGE

ACALL DELAY_1S

CJNE R5,#09H,LIFT

SJMP START

RET*/

****************************************************************************

串口通信读出写入程序

****************************************************************************

CH451_WRITE:

CLR EX0 禁止键盘中断

CLR CH451_LOAD 命令开始,此命令可以放在后面

MOV R7,#08H 将 ACC 中 8 位送出

CH451_WRITE_8: RRC A低位在前,高位在后

CLR CH451_DCLK

MOV CH451_DIN,C 送出一位数据

SETB CH451_DCLK 产生时钟上升沿通知 CH451 输入位数据

DJNZ R7,CH451_WRITE_8 位数据未完继续

MOV A,B

MOV R7,#04H 将 B 中 4 位送出

CH451_WRITE_4: RRC A低位在前,高位在后

CLR CH451_DCLK

MOV CH451_DIN,C 送出一位数据

SETB CH451_DCLK 产生时钟上升沿通知 CH451 输入位数据

DJNZ R7,CH451_WRITE_4 位数据未完继续

SETB CH451_LOAD 产生加载上升沿通知 CH451 处理命令数据

SETB EX0 允许键盘中断

RET

输入键值子程序

CH451_READ: CLR EX0 禁止键盘中断

CLR CH451_LOAD 命令开始

MOV A,#07H 读取键值命令的高 4 位 0111B

MOV R7,#04H 忽略 12 位命令的低 8 位

CH451_READ_4: RRC A低位在前,高位在后

CLR CH451_DCLK

MOV CH451_DIN,C 送出一位数据

SETB CH451_DCLK 产生时钟上升沿锁通知 CH451 输入位数据

DJNZ R7,CH451_READ_4 位数据未完继续

SETB CH451_LOAD 产生加载上升沿通知 CH451 处理命令数据

CLR A先清除键值单元以便移位

MOV R7,#07H 读入 7 位键值

CH451_READ_7:

MOV C,CH451_DOUT 读入一位数据

CLR CH451_DCLK 产生时钟下升沿通知 CH451 输出下一位

RLC A数据移入 ACC,高位在前,低位在后

SETB CH451_DCLK

DJNZ R7,CH451_READ_7 位数据未完继续

CLR IE0 清中断标志,读 *** 作过程中有低电平脉冲

SETB EX0 允许键盘中断

RET

END

刚做过,发给你参考下

这是原理图

51单片机简易计算器程序:

#include <reg51.h>

#include <math.h>

#define uchar unsigned char

#define uint unsigned int

//---------定义引脚--------------------

bit clr=0

bit ok=0

bit xiaoshu=0

bit jiego=0

bit first_1=1

bit first_2=1

sbit dout = P3^2

sbit load = P2^0

sbit din = P2^1

sbit dclk = P2^2

sbit beer=P0^1

sbit LCD1602_RS=P2^3

sbit LCD1602_RW=P2^4

sbit LCD1602_E=P2^5

//---------定义变量--------------------

uchar ch451_key=0xff

uchar yun_sign

uchar xiabiao=0

uchar tab[32]

uchar tab1[]={"welcome to use!"}

uchar tab2[]={" make by JunRu!"}

uchar tab3[]={"ERR0R"}

float opr_1=0,opr_temp=0,end=0,a

//---------声明函数--------------------

void ch451_init(void)//CH451初始化

void ch451_write(uint command)//写命令或数据到ch451

uchar ch451_read(void) //读按键值

uchar get_char(void)

void LCD_init(void)//初始化;

void delay(unsigned int k)//延时程序

void LCD_inter_command(unsigned char command)//写入控制字

void LCD_inter_dat(unsigned char dat)//写入要显示的数据

void set_xy(unsigned char x,unsigned char y)//找地址

void write(unsigned char date)//写入字符

void lcdbusy()//查忙时

void display(void)

void spec(void)

void get_end(void)

void hun_he(uchar n)

//-------- 主函数----------------------

void main()

{

uchar i

LCD_init()//LCD初始化;

ch451_init()//CH451初始化

EA = 1//打开中断

LCD_inter_command(0x01)//清屏

for(i=0i<=14i++)

{

LCD_inter_dat(tab1[i])

beer=0

delay(4000)//延时

beer=1

}

LCD_inter_command(0xc0)//从第二行开始显示

for(i=0i<=14i++)

{

LCD_inter_dat(tab2[i])

beer=0

delay(4000)//延时

beer=1

}

delay(0xffff)

delay(0xffff)

LCD_inter_command(0x01)

while(1)

{

if(ok)

{

display()

ok=0clr=1

}

}

}

//----------子函数--------------------

void hun_he(uchar n)

{int j

switch(n)

{

case '+':opr_temp=opr_temp+opr_1break

case '-':opr_temp=opr_temp-opr_1break

case '*':opr_temp=opr_temp*opr_1break

case '/':

{

if(a==0)//减数为零显错

{ LCD_inter_command(0xc0)

for(j=0j<=4j++)

{

LCD_inter_dat(tab3[j])

beer=0

delay(4000)//延时

beer=1

}

}

else

{opr_temp=opr_temp/opr_1}

break

}

default:break}

}

void ch451_init(void)//CH451初始化

{

EX0 = 1

din = 0

din = 1

ch451_write(0x403) //开显示

ch451_write(0x580) //BCD译码方式

}

void ch451_write(uint command)//写命令或数据到ch451

{ uchar i

EX0 = 0

load = 0

for(i=0i<12i++)

{

din = command&1

dclk = 0

command>>=1

dclk = 1

}

load = 1

EX0 = 1

}

uchar ch451_read(void)//读按键值

{ uchar key=0x07

uchar i

EX0=0

load = 0

for(i=0i<4i++)//将0111读入

{

din = key &1

dclk = 0

key>>=1

dclk =1

}

load = 1

key = 0

for(i=0i<7i++) //从CH451读出按键值

{

key<<=1

key|= dout

dclk =0

dclk =1

}

EX0 =1

return key

}

void EX0_ISR(void)interrupt 0 //中断程序

{

uchar temp

ch451_key=ch451_read()//将读出的按键值赋给变量

spec()

if(clr) {LCD_inter_command(0x01)clr=0}

temp=get_char()

if(temp){tab[xiabiao++]=tempLCD_inter_dat(temp)}

if(xiabiao>=16)LCD_inter_command(0xc0)//若大于16,则从第2行开始显示

if(ok) get_end()

beer=0

delay(3000)

beer=1

}

uchar get_char(void)

{

uchar dis=0

uint temp=0,temp1=0

switch(ch451_key)

{

case 0x40:dis='1'break

case 0x41:dis='2'break

case 0x42:dis='3'break

case 0x48:dis='4'break

case 0x49:dis='5'break

case 0x4A:dis='6'break

case 0x50:dis='7'break

case 0x51:dis='8'break

case 0x52:dis='9'break

case 0x58:dis='0'break

case 0x43:dis='+'break

case 0x4B:dis='-'break

case 0x53:dis='x'break

case 0x5B:dis='/'break

case 0x44:dis='!'break

case 0x5A:dis='='

ok=1 //遇到“=”,开始运算

break

case 0x59:dis='.'break//小数点

case 0x5C://删除键

LCD_inter_command(0x01)

xiabiao=0

break

default: break

}

return dis

}

void spec(void) //特殊功能键

{

switch(ch451_key)

{

case 0x4C:LCD_inter_command(0x10){if(xiabiao>0)xiabiao-=1}break//左移

case 0x54:LCD_inter_command(0x14){xiabiao+=1}break //右移

default:break

}

}

void delay(unsigned int k)//延时程序

{

while (k--)

}

void LCD_inter_command(unsigned char command)//写入控制字

{

delay(5000)

LCD1602_RS=0

LCD1602_RW=0

LCD1602_E=1

P1=command

LCD1602_E=0

lcdbusy()

}

void LCD_init(void)//初始化;

{delay(5000)

LCD_inter_command(0x01)//清屏

delay(5000)

LCD_inter_command(0x38)//设置为8位的数据接口,两行显示,5、7点字符

delay(5000)

LCD_inter_command(0x0E)//显示打开,光标开并闪烁

delay(5000)

}

void LCD_inter_dat(unsigned char dat)//写入要显示的数据

{

delay(5000)

LCD1602_RS=1

LCD1602_RW=0

LCD1602_E=1

P1=dat

LCD1602_E=0

lcdbusy()

}

void lcdbusy()//查忙

{

P1=0xFF

LCD1602_RS=0

LCD1602_RW=1

LCD1602_E=1

while((P1&0x80)==1)

}

void display(void)//转化在LCD上显示计算结果

{

int temp=end //浮点数

int i

uint xiao_temp

uint xx//浮点数的整数部分

if (end>-32769&&end<32768)

{

xx=fabs(end)

xiao_temp=(fabs(end)-xx)*1000//取出浮点数的小数部分

LCD_inter_command(0xc0)

if(end<0) LCD_inter_dat('-')beer=0delay(4000)beer=1//判断是否为负数,若是则显示负号

if(xx>9999) LCD_inter_dat((xx/10000)%10+'0')beer=0delay(4000)beer=1

if(xx>999) LCD_inter_dat((xx/1000)%10+'0')beer=0delay(4000)beer=1//在LCD上显示千位的数

if(xx>99)LCD_inter_dat((xx/100)%10+'0') beer=0delay(4000)beer=1//百位

if(xx>9)LCD_inter_dat((xx/10)%10+'0')beer=0delay(4000)beer=1//十位

LCD_inter_dat(xx%10+'0')beer=0delay(4000)beer=1//个位

if(xiao_temp!=0) //显示小数部分

{

LCD_inter_dat('.')beer=0delay(4000)beer=1

LCD_inter_dat((xiao_temp/100)%10+'0')beer=0delay(4000)beer=1

LCD_inter_dat((xiao_temp/10)%10+'0')beer=0delay(4000)beer=1

LCD_inter_dat(xiao_temp%10+'0')beer=0delay(4000)beer=1

}

}

else {LCD_inter_command(0xc0)//从第二行开始显示

for(i=0i<=4i++)

{ LCD_inter_dat(tab3[i])

beer=0

delay(4000)//延时

beer=1

}

}

}

void get_end(void)//计算子程序

{ float xiaoshu=1

uchar fu_flag=0

uchar xiao_flag=0

uchar lianji_sign

uchar i=0

uchar j

uchar n//正负标记符

while(i<=xiabiao)

{

while(tab[i]<=0x39&&tab[i]>=0x30)

{

n=0

opr_1*=10

opr_1+=tab[i++]-0x30

n='+'

}

switch(tab[i])

{

case '.': xiao_flag=1break//遇到小数点跳到“if(xiao_flag)”里

case '!': fu_flag=1break

case '+': xiaoshu=1yun_sign='+'if(opr_temp==0){end=opr_temp=opr_1}else hun_he(lianji_sign)opr_1=0lianji_sign='+'break

case '-': xiaoshu=1yun_sign='-'if(opr_temp==0){end=opr_temp=opr_1}else hun_he(lianji_sign)opr_1=0lianji_sign='-'break

case 'x': xiaoshu=1yun_sign='x'if(opr_temp==0){end=opr_temp=opr_1}else hun_he(lianji_sign)opr_1=0lianji_sign='*'break

case '/': xiaoshu=1yun_sign='/'if(opr_temp==0){end=opr_temp=opr_1}else hun_he(lianji_sign)a=opr_1opr_1=0lianji_sign='/'break

case '=':

switch(yun_sign)//进行运算

{

case '+':end=opr_temp+opr_1break

case '-':end=opr_temp-opr_1break

case 'x':end=opr_temp*opr_1break

case '/':{

if(a==0)//减数为零显错

{ LCD_inter_command(0xc0)

for(j=0j<=4j++)

{

LCD_inter_dat(tab3[j])

beer=0

delay(4000)//延时

beer=1

}

}

else

{end=opr_temp/opr_1}

break

}

default:break

}

ok=1//开始进行显示,标志位置1

xiabiao=0//小数的标志位清零

break

default:break

}

i++

if(xiao_flag)//表示小数

{

while(tab[i]<=0x39&&tab[i]>=0x30)

{

xiaoshu*=0.1

switch(n)

{

case '+': opr_1=opr_1+(tab[i++]-0x30)*xiaoshubreak

case '-': opr_1=opr_1-(tab[i++]-0x30)*xiaoshubreak

default:break}

xiao_flag=0

}

}

if(fu_flag)

{

while(tab[i]<=0x39&&tab[i]>=0x30)

{

n=0

opr_1=-opr_1*10

opr_1=-(opr_1+(tab[i++]-0x30))

n='-'

fu_flag=0

}

}

}

opr_1=0

opr_temp=0

xiabiao=0

xiaoshu=1

}


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

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

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

发表评论

登录后才能评论

评论列表(0条)

保存