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
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)