用汇编语言实现简易电压表

用汇编语言实现简易电压表,第1张

LED_0 EQU 30H

LED_1 EQU 31H

LED_2 EQU 32H

LED_3 EQU 33H

ADC EQU 35H

ST BIT P3.2

OE BIT P3.0

EOC BIT P3.1

ORG 00H

START: MOV LED_0,#00H

MOV LED_1,#00H

MOV LED_2,#00H

MOV LED_3,#00H

MOV DPTR,#TABLE

SETB P3.4

SETB P3.5

CLR P3.6

WAIT: CLR ST

SETB ST

CLR ST

JNB EOC,$

SETB OE

MOV ADC,P1

CLR OE

MOV A,ADC

MOV B,#51

DIV AB

MOV LED_3,A

MOV A,B

MOV B,#5

DIV AB

MOV LED_2,A

MOV LED_1,B

LCALL DISP

SJMP WAIT

DISP: MOV A,#3EH

CLR P2.3

MOV P0,A

LCALL DELAY

SETB P2.3

MOV A,LED_1

MOVC A,@A+DPTR

CLR P2.2

MOV P0,A

LCALL DELAY

SETB P2.2

MOV A,LED_2

MOVC A,@A+DPTR

CLR P2.1

MOV P0,A

LCALL DELAY

SETB P2.1

MOV A,LED_3

MOVC A,@A+DPTR

ORL A,#80H

CLR P2.0

MOV P0,A

LCALL DELAY

SETB P2.0

RET

DELAY: MOV R6,#10

D1: MOV R7,#250

DJNZ R7,$

DJNZ R6,D1

RET

TABLE: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,

END

方 法:

/// <summary>

/// 只能通过CreateInstance方法来创建类的实例。单例模式

/// </summary>

public static ElectricityMeter CreateInstance()

{

return _instance

}

/// <summary>

/// 打开设备

/// </summary>

/// <param name="portName">串口号</param>

/// <param name="frm">调用这个类的窗体。</param>

public void Open( string portName, Form frm )

{

try

{

// 初始化窗体对象

_frm = frm

_frm.FormClosing += new FormClosingEventHandler( _frm_FormClosing )

//初始化SerialPort对象

_serialPort.PortName = portName

_serialPort.BaudRate = 2400// 请将设备的波特率设置为此。

_serialPort.DataBits = 8

_serialPort.StopBits = StopBits.One

_serialPort.Parity = Parity.Even

_serialPort.Open()

}

catch( Exception e )

{

MessageBox.Show( e.Message )

}

}

/// <summary>

/// 关闭设备。

/// </summary>

public void Close()

{

if( _serialPort.IsOpen == true )

{

_serialPort.Close()

_serialPort.Dispose()

}

}

/// <summary>

/// 获取耗电量

/// </summary>

public Decimal GetPowerConsumption()

{

if( _serialPort.IsOpen == true )

{

// 十六进制的命令字符串

string strCmd = "68 AA AA AA AA AA AA 68 11 04 33 33 33 33 AD 16"

// 转换为十六进制的字节数组

string[] strs = strCmd.Split( new char[] { ' ' } )// 空格分组

byte[] cmdBytes = new byte[ strs.Length ]

// 转换为十进制的字节数组

for( int i = 0i <cmdBytes.Lengthi++ ) {

cmdBytes[ i ] = Convert.ToByte( strs[ i ], 16 )// 16进制转换为10进制

}

_serialPort.Write( cmdBytes, 0, cmdBytes.Length )

System.Threading.Thread.Sleep( 500 ) // 500ms内应当有响应

byte[] resultBytes = new byte[ 21 ]// 容量为21的字节数组

_serialPort.Read( resultBytes, 0, resultBytes.Length )

string n1 = Convert.ToString( resultBytes[ 18 ] - 51, 16 )// 将十进制转成16进制的字符串

string n2 = Convert.ToString( resultBytes[ 17 ] - 51, 16 )// 将十进制转成16进制的字符串

string n3 = Convert.ToString( resultBytes[ 16 ] - 51, 16 )// 将十进制转成16进制的字符串

string n4 = Convert.ToString( resultBytes[ 15 ] - 51, 16 )// 将十进制转成16进制的字符串

string resultString = n1 + n2 + n3 + "." + n4

return Decimal.Parse( resultString )

}

else

{

throw new Exception( "串口没有打开" )

}

}

/// <summary>

/// 在窗体关闭的时候关闭串口连接。

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

void _frm_FormClosing( object sender, FormClosingEventArgs e )

{

this.Close()

}

}

汇编如下:

S_SET BIT P3.4 秒增加1按钮位

M_SET BIT P3.5 分增加1按钮位

H_SET BIT P3.7 小时增加1按钮位

SECONDEQU 30H 秒计数值变量 

MINUTEEQU 31H 分计数值变量

HOUR EQU 32H 小时计数值变量

TCNT EQU 34H 1秒定时计数器

ORG 00H 起始地址

JMP START

ORG 0BH Timer0中断向量地址

JMP INT_T0

START:

MOVDPTR,#TABLE 装七段数码管段码数据表TABLE

MOVHOUR,#0 计数值全部清0

MOVMINUTE,#0

MOVSECOND,#0

MOVTCNT,#0

MOVTMOD,#01H Timer 0作定时器,模式1

MOVTH0,#(65536-50000)/256定时50毫秒

MOVTL0,#(65536-50000)MOD 256

MOVIE,#82H中断使能

SETBTR0 启动Timer 0

以下是判断秒、分、小时增加1按钮是否被按下

A1:

CALL DISPLAY

JNB S_SET,S1 判断秒按钮

JNB M_SET,S2判断分按钮

JNB H_SET,S3 判断小时按钮

JMP A1循环检测

S1:

CALL DELAY去抖动

JBS_SET,A1

INC SECOND 秒位计数值加1

MOVA,SECOND A=SECOND

CJNEA,#60,J0 判断是否到60秒

MOVSECOND,#0 如果到了就清0秒位计数值

JMP K1跳到K1段

S2:

CALL DELAY

JBM_SET,A1

K1:

INC MINUTE 分位计数值加1

MOVA,MINUTE A=MINUTE

CJNEA,#60,J1 判断是否到60分

MOVMINUTE,#0 如果到了就清0分位计数值

JMP K2

S3:

CALL DELAY

JBH_SET,A1

K2:

INC HOUR 小时计数值加1

MOVA,HOUR A=HOUR

CJNEA,#24,J2 判断是否到24小时

MOVHOUR,#0 如果到了就清0秒、分、小时位计数值

MOVMINUTE,#0

MOVSECOND,#0

JMP A1

以下程序等待秒、分、小时按钮放开

J0:

JBS_SET,A1

CALL DISPLAY

JMP J0

J1:

JBM_SET,A1

CALL DISPLAY

JMP J1

J2:

JBH_SET,A1

CALL DISPLAY

JMP J2

Timer0中断服务子程序, 进行秒、分、小时的计时

INT_T0:

MOVTH0,#(65536-50000)/256装计数初始值

MOVTL0,#(65536-50000)MOD 256

INC TCNT 1秒计数器增加1

MOVA,TCNTA=TCNT

CJNEA,#20,RETUNE 计时1秒

INC SECOND 秒计数器增加1

MOVTCNT,#0 清零TCNT

MOVA,SECOND A=SECOND

CJNEA,#60,RETUNE 计时60秒

INC MINUTE 分计数器增加1

MOVSECOND,#0 清零秒

MOVA,MINUTE A=MINUTE

CJNEA,#60,RETUNE 计时60分

INC HOUR 小时计数器增加1

MOVMINUTE,#0 清零分

MOVA,HOUR A=HOUR

CJNEA,#24,RETUNE 计时24小时 

MOVHOUR,#0 秒、分、小时计数值清0

MOVMINUTE,#0

MOVSECOND,#0

MOVTCNT,#0

RETUNE:

RETI中断服务子程序结束

以下为七段数码管显示的子程序

DISPLAY:

MOVA,SECOND A=SECOND,显示秒

MOVB,#10B=10

DIV AB A除以B

MOV P2,#00100000B 使能秒的十位

MOVC A,@A+DPTR七段数码管段码数据装入A

MOVP0,A 从P0口输出

CALL DELAY

ORL P2,#0FFH 熄灭七段数码管

MOVA,B A=B

MOV P2,#00000000B 使能秒的个位

MOVC A,@A+DPTR七段数码管段码数据装入A

MOVP0,A 从P0口输出

CALL DELAY

ORL P2,#0FFH 熄灭七段数码管

MOVA,MINUTE A=MINUTE,显示分

MOVB,#10B=10

DIV AB A除以B

MOV P2,#01100000B 使能分的十位

MOVC A,@A+DPTR七段数码管段码数据装入A

MOVP0,A 从P0口输出

CALL DELAY

ORL P2,#0FFH 熄灭七段数码管

MOVA,B A=B

MOV P2,#01000000B 使能分的个位

MOVC A,@A+DPTR七段数码管段码数据装入A

MOVP0,A 从P0口输出

CALL DELAY

ORL P2,#0FFH 熄灭七段数码管

MOVA,HOUR A=HOUR,显示小时

MOVB,#10B=10

DIV AB A除以B

MOV P2,#10100000B 使能小时的十位

MOVC A,@A+DPTR七段数码管段码数据装入A

MOVP0,A 从P0口输出

CALL DELAY

ORL P2,#0FFH 熄灭七段数码管

MOVA,B A=B

MOV P2,#10000000B 使能小时的个位

MOVC A,@A+DPTR七段数码管段码数据装入A

MOVP0,A 从P0口输出

CALL DELAY

ORL P2,#0FFH 熄灭七段数码管

RET

TABLE: 七段数码管显示码表

DB 40H,79H,24H,30H,19H

DB 12H,02H,78H,00H,10H

DELAY: 延时子程序

MOVR6,#2

D1:

MOVR7,#250

DJNZR7,$

DJNZR6,D1

RET

END


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

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

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

发表评论

登录后才能评论

评论列表(0条)

保存