单片机论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 736|回复: 0
收起左侧

单片机LCD1602时钟温度显示汇编程序(注释很全)仿真

[复制链接]
dddddddz 发表于 2019-1-26 14:51 | 显示全部楼层 |阅读模式
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
0.png 0.png

带有全面中文注释的单片机源程序如下:
  1. ;**********************************************************************
  2. ;晶振为12MHZ,显示实时时间,温度
  3. ;测量温度范围为-55~+99摄氏度
  4. ;***********************************************************************
  5.                 T_RST                        EQU                P1.5                //DS1302复位线引脚
  6.                 T_CLK                        EQU                P1.6                //DS1302时钟线引脚
  7.                 T_IO                        EQU                P1.7                //DS1302数据线引脚

  8.                 TEM_L                        EQU                40H                        //存放从DS18B20中读出的高、低位温度值
  9.                 TEM_H                        EQU                41H               
  10.                 TEM_NUM                        EQU                42H                        //存放温度转换后的整数部分
  11.                 FLAG0                        EQU                45H                        //FLAG0存放温度的符号
  12.                 DQ                                EQU                P2.3                //DS18B20数据线

  13.                 RS                                BIT                P2.0                //LCD控制线定义
  14.                 RW                                BIT                P2.1               
  15.                 E                                BIT                P2.2

  16.                 SKIP_B20                EQU                0CCH                //DS18B20跳过ROM命令
  17.                 START_B20                EQU                44H                        //DS18B20温度变换命令
  18.                 READDS                        EQU                0BEH                //DS18B20读暂存器命令
  19.                
  20.                 ORG                0000H
  21.                 AJMP        MAIN
  22.                 ORG                0100H
  23. MAIN:        MOV                SP,#90H
  24.                 ACALL        LCD_INT                                          //进行LCD初始化
  25.                 MOV                A,#8BH                                                //在LCD第一行第12列显示WEEK
  26.                 LCALL        W_COM
  27.                 MOV                A,#57H                                                //字母'W'的字符库为01010111
  28.                 LCALL        W_DAT
  29.                 MOV                A,#45H                                                //字母'E'的字符库为01000101
  30.                 LCALL        W_DAT
  31.                 MOV                A,#45H                                                
  32.                 LCALL        W_DAT
  33.                 MOV                A,#4BH                                                //字母'K’的字符库为01001011
  34.                 LCALL        W_DAT
  35.                 MOV                A,#0C0H                                                //第二行第一列显示TIME
  36.                 LCALL        W_COM
  37.                 MOV                A,#54H                                                //字母'T'的字符库为01010100
  38.                 LCALL        W_DAT
  39.                 MOV                A,#49H                                                //字母'I'的字符库为01001001
  40.                 LCALL        W_DAT
  41.                 MOV                A,#4DH                                                //字母'M'的字符库为01001101
  42.                 LCALL        W_DAT
  43.                 MOV                A,#45H                                                //字母'E'的字符库为01000101
  44.                 LCALL        W_DAT
  45.                
  46.         

  47.                  MOV                60H,#00H                                        //设置秒存储单元
  48.                 MOV                61H,#00H                                        //设置分存储单元
  49.                 MOV                62H,#16H                                        //设置时存储单元
  50.                 MOV                63H,#05H                                        //设置日存储单元
  51.                 MOV                64H,#01H                                        //设置月存储单元
  52.                 MOV                65H,#03H                                        //设置星期存储单元
  53.                 MOV                66H,#18H                                        //设置年存储单元
  54.                 LCALL        SET1302                                                //向DS1302写入时间

  55. REP:          LCALL        GET1302                                                //读出时间
  56.             LCALL        GET_TEM                                                  //读出转换后的温度值
  57.                   LCALL        TEM_COV

  58. ;;;;;;;;;;在LCD第一行显示年月日和星期;;;;;;;;;;                        
  59.                  MOV            A,#80H                                                 //显示在LCD第一行第一列
  60.                    LCALL        W_COM                                                 //调用LCD写命令子程序
  61.                 MOV            A,#'2'
  62.                  ACALL        W_DAT                                                 //调用LCD写数据子程序
  63.                  MOV            A,#'0'
  64.                  ACALL        W_DAT
  65.                  MOV            A,56H                                                //年拆分成十位与个位,转换字符显示
  66.                  MOV            B,#10H
  67.                  DIV            AB
  68.                  ADD            A,#30H                                                 //数字的字符库从00110000B即30H开始
  69.                  ACALL        W_DAT
  70.                  MOV           A,B
  71.                  ADD            A,#30H
  72.                  ACALL        W_DAT
  73.                  MOV            A,#'-'
  74.                  ACALL        W_DAT
  75.                  MOV            A,54H                                                  //月拆分成十位与个位,转换字符显示
  76.                  MOV            B,#10H
  77.                  DIV            AB
  78.                  ADD            A,#30H
  79.                  ACALL        W_DAT
  80.                  MOV            A,B
  81.                  ADD            A,#30H
  82.                  ACALL        W_DAT
  83.                  MOV            A,#'-'
  84.                  ACALL        W_DAT
  85.                  MOV            A,53H                                                //日拆分成十位与个位,转换字符显示
  86.                  MOV            B,#10H
  87.                  DIV            AB
  88.                  ADD            A,#30H
  89.                  ACALL        W_DAT
  90.                  MOV            A,B
  91.                  ADD            A,#30H
  92.                  ACALL        W_DAT
  93.                 MOV          A,#8FH                                                //设置LCD显示星期的位置为第一行第十六列
  94.                   LCALL        W_COM
  95.                  MOV            A,55H                                                 //显示星期
  96.                  ADD            A,#30H
  97.                  LCALL        W_DAT

  98. ;;;;;;;;;;在LCD第二行显示时分秒和温度;;;;;;;;;;;;;
  99.                 MOV                A,#0C4H                                                //写入显示缓冲区的起始地址为第二行第五列开始
  100.                    LCALL        W_COM
  101.                    MOV            A,52H                                                  //小时拆分成十位与个位,转换字符显示
  102.                  MOV            B,#10H
  103.                  DIV            AB
  104.                  ADD            A,#30H
  105.                  LCALL        W_DAT
  106.                  MOV            A,B
  107.                  ADD            A,#30H
  108.                    LCALL        W_DAT
  109.                  MOV            A, #':'
  110.                  LCALL        W_DAT
  111.                  MOV            A,51H                                                  //分拆分成十位与个位,转换字符显示
  112.                  MOV            B,#10H
  113.                  DIV            AB
  114.                  ADD            A,#30H
  115.                  LCALL        W_DAT
  116.                  MOV            A,B
  117.                  ADD            A,#30H
  118.                  LCALL        W_DAT
  119.                  MOV            A, #':'
  120.                   LCALL        W_DAT
  121.                  MOV            A,50H                                                 //秒拆分成十位与个位,转换字符显示
  122.                  MOV            B,#10H
  123.                  DIV            AB
  124.                  ADD            A,#30H
  125.                  LCALL        W_DAT
  126.                  MOV            A,B
  127.                  ADD            A,#30H
  128.                   LCALL        W_DAT
  129.                   MOV                A,#0CDH                                                //温度显示在LCD第二行第十四列
  130.                 LCALL        W_COM
  131.                   MOV                A,FLAG0                                                //显示温度正负号
  132.                 ACALL        W_DAT
  133.                    MOV                A,TEM_NUM                                        //温度整数拆分成十位和个位显示
  134.                 MOV                B,#0AH                                       
  135.                 DIV                AB                                                        //商送给A,余数送给B
  136.                 ADD                A,#30H
  137.                 CJNE        A,#30H,REP1                                        //如果十位为0,则不显示
  138.                 MOV                A,#20H                                                //字符库中00100000B(20H)为空白
  139. REP1:        ACALL        W_DAT                                                //调用LCD写数据子程序
  140.                 MOV                A,B                                                        //将求得的余数送给A
  141.                 ADD                A,#30H
  142.                 ACALL        W_DAT                                                //调用LCD写数据子程序
  143.                 LJMP           REP

  144. /******************时间**************************/
  145. ;;;;;;;;累加器A写一字节到DS1302;;;;;;;;;;;;;
  146. WE:                MOV                70H,#08H                                                //一个字节八位,移动八次
  147. INB1:        MOV                A,B                                                                //将命令字送给A
  148.                 RRC                A                                                                //通过A移入进位标志位C
  149.                 MOV                B,A
  150.                 MOV                T_IO,C                                                        //移入到芯片内
  151.                 SETB        T_CLK
  152.                 CLR                T_CLK
  153.                 DJNZ        70H,INB1
  154.                 RET

  155. ;;;;;;;;读一字节到累加器A中;;;;;;;;;;;;;;;;;
  156. READ:        MOV                70H,#08H                                                //一个字节八位,移动八次
  157. OUTB1:        MOV                C,T_IO                                                        //从芯片内移动到进位标志位C
  158.                 RRC                A                                                                //通过C再移入累加器A中
  159.                 SETB        T_CLK
  160.                 CLR                T_CLK
  161.                 DJNZ        70H,OUTB1
  162.                 RET

  163. ;;;;;;;;;向DS1302写入时间子程序;;;;;;;;;;;;;;
  164. SET1302:CLR          T_RST                                                           //RST引脚为低电平,数据传送终止
  165.         CLR          T_CLK                                                        //清零时钟总线
  166.                 SETB         T_RST                                                        //RST引脚为高电平,逻辑控制有效
  167.                 MOV          B,#8EH                                                        //控制命令字(10001110-进行存取时间,写操作)
  168.                 LCALL          WE                                                                //调用写字节命令
  169.                 MOV            B,#00H                                                        //写操作前清写保护位W
  170.                 LCALL          WE
  171.                 SETB           T_CLK
  172.                 CLR            T_RST
  173.         MOV            R0,#60H                                                 //秒 分 时  日 月 星期  年  数据存储在60-66H单元
  174.             MOV            R7,#07H                                                        //共7个字节
  175.         MOV            R1,#80H                                                        //写秒寄存器命令
  176. S1:                CLR                T_RST
  177.                 CLR                T_CLK
  178.                 SETB        T_RST
  179.                 MOV                B,R1                                                        //写入写秒指令
  180.                 LCALL        WE
  181.                 MOV                A,@R0                                                        //将秒存储单元中的数值送给A
  182.                 MOV                B,A
  183.                 LCALL        WE
  184.                 INC                R0                                                                //R0加一,指向下一个写入的日历、时钟数据
  185.                 INC                R1                                                                //指向下一个时间寄存器
  186.                 INC                R1
  187.                 SETB        T_CLK
  188.                 CLR                T_RST
  189.                 DJNZ        R7,S1
  190.                 CLR                T_RST
  191.                 CLR                T_CLK
  192.                 SETB        T_RST
  193.                 MOV                B,#8EH                                                        //控制命令字(10001110-进行存取时间,写操作)
  194.                 LCALL        WE
  195.                 MOV                B,#80H                                                        //控制寄存器中WP置1
  196.                 LCALL        WE
  197.                 SETB        T_CLK
  198.                 CLR                T_RST                                                        //结束写过程
  199.                 RET

  200. ;;;;;;;;;;;;;;;读时间子程序;;;;;;;;;;;;;;;;;               
  201. GET1302:MOV           R0,#50H
  202.         MOV           R7,#7
  203.         MOV           R1,#81H                                                 //读秒寄存器命令
  204. G1:                CLR            T_RST
  205.         CLR            T_CLK
  206.         SETB           T_RST
  207.         MOV            B,R1                                                          //写入读秒寄存器命令
  208.         LCALL          WE                                                               
  209.         LCALL          READ
  210.         MOV            @R0,A                                                          //存入读出数据
  211.         INC            R0                                                          //指向下一个存放日历、时钟的存储单元
  212.         INC            R1                                                          //指向下一个日历、时钟寄存器
  213.         INC            R1   
  214.         SETB           T_CLK
  215.         CLR            T_RST
  216.         DJNZ           R7,G1                                                         //未读完,继续读下一个
  217.         RET        
  218.                
  219. /********************温度************************/
  220. ;;;;;;;;;;;;;;DS18B20复位程序;;;;;;;;;;;;;;;;;
  221. B20_INT:SETB        DQ                                                                 //将数据线置高电平“1”
  222.                 NOP                                                                                  //延时        
  223.                 NOP
  224.                 CLR                DQ                                                                //数据线拉到低电平“1”
  225.                 MOV                R7,#0CH                                                        //延时60*12=720US
  226. INT_DEL:ACALL        DEL60US
  227.                 DJNZ        R7,INT_DEL
  228.                 SETB        DQ                                                                //数据线拉到高电平“1”
  229.                 ACALL        DEL60US                                                        //延时等待
  230.                 ACALL        DEL60US
  231.                 MOV                C,DQ                                                        //将数据线的状态送给C,判断初始化是否成功,是否产生一个低电平
  232.                 JC                ERROR                                                        //如果C等于1,则跳出,初始化失败
  233.                 ACALL        DEL60US                                                        //初始化成功,CPU读到数据线上的低电平,继续延时
  234.                 ACALL        DEL60US
  235.                 ACALL        DEL60US
  236.                 ACALL        DEL60US
  237.                 RET
  238. ERROR:        CLR                DQ                                                                //初始化未成功,继续进行初始化
  239.                 SJMP        B20_INT
  240.                 RET

  241. ;;;;;;;;;;;;;;;;;读DS18B20一个字节到累加器A子程序;;;;;;;;;;;;
  242. R_BYTE:        MOV                R7,#08H                                                        //读取8位为一字节
  243.                 SETB        DQ
  244.                 NOP
  245.                 NOP
  246. LOOP:        CLR                DQ                                                                //将数据线从高电平拉为低电平时,作为一个读周期的开始
  247.                 NOP                                                                                //延时,保证低电平至少为1US
  248.                 NOP
  249.                 NOP
  250.                 SETB        DQ                                                               
  251.                 MOV                R6,#07H                                                        //循环到A的最高位
  252.                 DJNZ        R6,[        DISCUZ_CODE_1        ]nbsp;                                                         
  253.                 MOV                C,DQ                                                        //将数据线中的值送给进位标志位C
  254.                 ACALL        DEL60US
  255.                 RRC                A                                                                //累加器A带进位右移
  256.                 SETB        DQ
  257.                 DJNZ        R7,LOOP                                                        //将一字节读到累加器A
  258.                 ACALL        DEL60US
  259.                 ACALL        DEL60US
  260.                 RET
  261.                
  262. ;;;;;;;;;;;;;累加器A写到DS18B20子程序;;;;;;;;;;
  263. W_BYTE:        MOV                R7,#08H                                                         //将8位连续数据(一字节)写入A
  264.                 SETB        DQ                                                                //拉高数据线
  265.                 NOP
  266.                 NOP
  267. LOOP1:        CLR                DQ                                                                //将数据线拉到低电平,作为写周期的开始
  268.                 MOV                R6,#07H                                                        //循环到累加器A的最高位Acc.7
  269.                 DJNZ        R6,$
  270.                 RRC                A                                                                //从累加器A的最高位开始写入
  271.                 MOV                DQ,C                                                        //将进位C送给DS18B20(写入时序,0或者1时序)
  272.                 ACALL        DEL60US                                                        //保持60US
  273.                 SETB        DQ                                                                //在15US内将数据线拉为高电平
  274.                 DJNZ        R7,LOOP1                                                //将一字节写入A
  275.                 RET
  276. DEL60US:MOV                R6,#1EH                                                        //延时(30*2)us
  277.                 DJNZ        R6,$
  278.                 RET

  279. ;;;;;;;;;;;读温度子程序;;;;;;;;;;;;;;;;;;
  280. GET_TEM:ACALL        B20_INT                                                        //DS18B20复位程序
  281.                 MOV                A,#0CCH                                                        //DS18B20跳过ROM命令
  282.                 ACALL        W_BYTE                                                        //调用写DS18B20子程序
  283.                 ACALL        DEL60US
  284.                 ACALL        DEL60US
  285.                 MOV                A,#44H                                                        //DS18B20温度转换命令,开始装换温度
  286.                 ACALL        W_BYTE                                                        //调用写DS18B20子程序
  287.                 ACALL        DEL60US
  288.                 ACALL        B20_INT                                                        //写完之后,将DS18B20复位
  289.                 MOV                A,#0CCH                                                        //DS18B20跳过ROM命令
  290.                 ACALL        W_BYTE                                                        //调用写DS18B20子程序
  291.                 ACALL        DEL60US
  292.                 MOV                A,#0BEH                                                        //DS18B20读暂存器命令
  293.                 ACALL        W_BYTE                                                        //调用写DS18B20子程序
  294.                 ACALL        DEL60US
  295.                 ACALL        R_BYTE                                                        //读温度低字节
  296.                 MOV                TEM_L,A                                                        //将读出的温度低字节保存在40H
  297.                    ACALL        R_BYTE                                                        //读温度高字节
  298.                 MOV                TEM_H,A                                                        // 将读出的温度高字节保存在41H
  299.                 RET

  300. ;;;;;将从DS18B20中读出的温度转换成整数显示;;;;;;;;;;;;
  301. TEM_COV:MOV                FLAG0,#'+'                                                //设置当前温度为正,并且存放在45H
  302.                 MOV                A,TEM_H                                                        //将读取的温度高字节送给A
  303.                 SUBB        A,#0F8H                                                        //判断C的值是否为1,为1则为正,为0则为负
  304.                 JC                TEM0                                                        //看温度值是否为负,不是(C=1),转
  305.                 MOV                FLAG0,#'-'                                                //是,置FLAG0为负
  306.                 MOV                A,TEM_L                                                        //将读取的温度低字节送给A
  307.                 CPL                A                                                                //求此时负值温度的补码
  308.                 ADD                A,#01H
  309.                 MOV                TEM_L,A                                                        //将求得的补码存放在40H
  310.                 MOV                A,TEM_H                                                         //将读取的温度高字节送给A
  311.                 CPL                A
  312.                 ADDC        A,#01H
  313.                 MOV                TEM_H,A                                                        //在将其补码放在41H
  314. TEM0:        MOV                A,TEM_L                                                        //存放整数部分到TEMPER_NUM
  315.                 ANL                A,#0F0H                                                        //取出温度低字节的高四位
  316.                 SWAP        A                                                                //将取出的高四位存放在A中低四位位置
  317.                 MOV                TEM_NUM,A                                                //将其存放在42H
  318.                 MOV                A,TEM_H
  319.                 SWAP        A
  320.                 ORL                A,TEM_NUM
  321.                 MOV                TEM_NUM,A
  322.                 RET

  323. /***************LCD显示*******************/
  324. ;;;;;;LCD初始化子程序;;;;;;;;;;;;
  325. LCD_INT:MOV                A,#00000001H                                        //清屏
  326.                 ACALL        W_COM                                                        //调用读命令子程序
  327.                 MOV                A,#00111000B                                        //传输8位数据,显示两行,使用5*7的字符
  328.                 LCALL        W_COM
  329.                 MOV                A,#00001100B                                        //显示器开,光标关,字符不闪烁
  330.                 LCALL        W_COM
  331.                 MOV                A,#00000110B                                        //字符不动,光标自动右移一格
  332.                 LCALL        W_COM
  333.                 RET
  334. ;;;;;写入命令子程序(RS=0,RW=0);;;;;;
  335. W_COM:        ACALL        F_BUSY
  336.                 CLR                E
  337.                 CLR                RS
  338.                 CLR                RW
  339.                 SETB        E
  340.                 MOV                P0,A
  341.                 CLR                E
  342.                 RET
  343. ;;;;;写入数据子程序(RS=1,RW=0);;;;;
  344. W_DAT:        ACALL        F_BUSY
  345.                 CLR                E
  346.                 SETB        RS                                                   
  347.                 CLR                RW
  348.                 SETB        E
  349.                 MOV                P0,A
  350.                 CLR                E
  351.                 RET

  352. ;;;;;查忙子程序;;;;;;;;;;;;;
  353. F_BUSY:        PUSH        ACC
  354.                 MOV                P0,#0FFH
  355.                 CLR                RS                                                                //忙标志
  356.                 SETB        RW                                                
  357. WAIT:        CLR                E                                                                //给使能端有效信号(下降沿触发)
  358.                 SETB        E
  359.                 JB                P0.7,WAIT                                                //直接寻址位P0.7是否为1,为1则忙,继续等待
  360.                 POP                ACC
  361.                 RET
  362.                 END                                                
  363.                                                         
复制代码

所有资料51hei提供下载:
LCD1602时钟温度显示+仿真.zip (77.69 KB, 下载次数: 18)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|单片机论坛 |51黑电子论坛单片机 联系QQ:125739409;技术交流QQ群582644647

Powered by 单片机教程网

快速回复 返回顶部 返回列表