数码之家

 找回密码
 立即注册
搜索
查看: 6132|回复: 13

[C51] 初学C语言写的RX8025T时钟程序,开源,欢迎点评和指教

[复制链接]
发表于 2021-6-18 19:52:24 | 显示全部楼层 |阅读模式

爱科技、爱创意、爱折腾、爱极致,我们都是技术控

您需要 登录 才可以下载或查看,没有账号?立即注册

x
这个电路原本设计是给一台机器作控制用途,下面的代码是其中计时部分,单片机是STC8G1K17+RX8025T+LCD1602
我以前是学汇编语言的,今年开始学C语言,
下面程序是我在学习过程中不断修改积累下来的,程序里存在一些是测试用途的代码, 程序里参照和用到他人的代码在注释那作了说明
我新手的,写得很啰嗦,希望指教。

5b1e17330a3fc6629a4dfd0b1151832.jpg
113.JPG

  1.                                                                                                                                                                                     
  2.         #include<stc8g.h>
  3.         #include  "intrins.h"

  4.         sbit sw1 = P3^1;
  5.         sbit sw2 = P3^2;
  6.         sbit sw3 = P3^3;
  7.         sbit sw4 = P3^4;
  8.         sbit sw5 = P3^5;
  9.         sbit sw6 = P3^6;
  10.         sbit sw7 = P3^7;
  11.         
  12.         sbit SWEN = P1^6;  //按键选通口        
  13.     sbit LED_P31 = P3^1;        // 低电平发亮

  14.          sbit RUN_TST= P5^4; //检测输入,低电平时确认有测试动作
  15.     sbit OUT1 = P5^5; //第1路输出  高电平时接通
  16.     sbit BUZ = P3^0;   //报警输出,为0时有响声
  17.         sbit POW_TST = P1^7;  //电压过低检测输入,输入为低电平时即电压过低


  18.    sbit LCD_D0  =  P1^2;
  19.    sbit  LCD_D1  =  P1^3 ;
  20.    sbit  LCD_D2  =  P3^2 ;
  21.    sbit  LCD_D3  =  P3^3 ;
  22.    sbit  LCD_D4  =  P3^4 ;
  23.    sbit  LCD_D5  =  P3^5 ;
  24.    sbit  LCD_D6  =  P3^6 ;
  25.    sbit  LCD_D7  =  P3^7;
  26.    sbit  LCD_RS  =  P1^0;   //LCD1602 的 RS端  ,1-数据,0-指令
  27.    sbit  LCD_EN  =  P1^1 ;  //LCD1602 的 E端   ,先从低变高,再变低,以确认输入数据或命令
  28.    //-----------------------------------------------------------------------------------------
  29.                             //iic串口控制寄存器定义         **********下面宏定义来自STC官网的例程
  30.          
  31.         #define I2CCFG          (*(unsigned char volatile xdata *)0xfe80)  // #define又称宏定义,标识符为所定义的宏名,简称宏。
  32.         #define I2CMSCR         (*(unsigned char volatile xdata *)0xfe81) //volatile的本意是“易变的”
  33.         #define I2CMSST         (*(unsigned char volatile xdata *)0xfe82)
  34.         #define I2CSLCR         (*(unsigned char volatile xdata *)0xfe83)
  35.         #define I2CSLST         (*(unsigned char volatile xdata *)0xfe84)
  36.         #define I2CSLADR        (*(unsigned char volatile xdata *)0xfe85)
  37.         #define I2CTXD          (*(unsigned char volatile xdata *)0xfe86)
  38.         #define I2CRXD          (*(unsigned char volatile xdata *)0xfe87)
  39.         #define I2CMSAUX        (*(unsigned char volatile xdata *)0xfe88)

  40.        sbit SDA = P1^4;
  41.        sbit SCL = P1^5;         

  42.           unsigned char xdata I2C_ADDR1; //I2C从器件的硬件地址存放点
  43.           unsigned char xdata I2C_ADDR2; //I2C从器件的数据地址首址存放点
  44.           unsigned char xdata I2C_X;  //I2C数据每次存放或取出个数,最大16字节
  45.           unsigned char xdata I2C_i=0; //主器件的数据地址首址
  46.    //--------------------------------------------------------------------------
  47.     #define ADCTIM (*(unsigned char volatile xdata *)0xfea8)         //ADC转换控制寄存器定义
  48.    

  49.         
  50.          unsigned char xdata LCD1602RAM1[2][16]={
  51.          {0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20},                  //LCD1602的缓存,初始值是空格20H
  52.          {0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20}
  53.          };
  54.          
  55.          unsigned char xdata I2C_1[64]={           //I2C读或写的临时缓存
  56.          0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
  57.          0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
  58.          0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
  59.          0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
  60.          };

  61.                   //**************************************************************************
  62.            unsigned char xdata kkeysta[7] ={    //全部按键的当前状态
  63.                             1,1,1,1,1,1,1,
  64.            };

  65.            signed char xdata SWJC1=0;   //用于按键位置计数,带符号整形,用以小于0的计数判断

  66.          //---------------------时间存放 每个变量存放一个BCD数

  67.           unsigned char xdata SEC1;   //秒个位
  68.           unsigned char xdata SEC10;   //秒十位
  69.           unsigned char xdata MIN1=0;    //分个位
  70.           unsigned char xdata MIN10;    //分十位
  71.           unsigned char xdata HOUR1;   //时个位
  72.           unsigned char xdata HOUR10;   //时十位
  73.           unsigned char xdata DAY1;     //日个位
  74.           unsigned char xdata DAY10;     //日十位
  75.           unsigned char xdata MONTH1;         //月个位
  76.           unsigned char xdata MONTH10;         //月十位
  77.           unsigned char xdata YEAR1;     //年个位
  78.           unsigned char xdata YEAR10;     //年十位

  79.           //-----------------------------------------------

  80.          unsigned char bdata LCD1602RAM2;  //LCD1602的写入缓冲
  81.          sbit LCD1602RAM2_D0= LCD1602RAM2^0;
  82.          sbit LCD1602RAM2_D1= LCD1602RAM2^1;
  83.          sbit LCD1602RAM2_D2= LCD1602RAM2^2;
  84.          sbit LCD1602RAM2_D3= LCD1602RAM2^3;
  85.          sbit LCD1602RAM2_D4= LCD1602RAM2^4;
  86.          sbit LCD1602RAM2_D5= LCD1602RAM2^5;
  87.          sbit LCD1602RAM2_D6= LCD1602RAM2^6;
  88.          sbit LCD1602RAM2_D7= LCD1602RAM2^7;

  89.             unsigned int xdata nsec1=0;        //用于闪烁显示的时间计数
  90.          
  91.            unsigned char fabc1 = 0; //计数标志
  92.           unsigned char xdata SW7_S1=0;         //按键SW7的长按标志1
  93.           unsigned int xdata SW7_S2=0;         //按键SW7的长按计时
  94.           //-------------------------------------------------------------
  95.            void keysm();           //按键扫描函数
  96.             void keycl();           //按键处理函数

  97.            void SWABC1();   //时间数值调整函数
  98.            void SET_RTC();   //设置好的数据保存到RX8025T
  99.          //**************************************************************************
  100.          void LCD_SC1();     ////全屏显示数据写入程序
  101.          void SCXL();    //LCD闪烁显示操作
  102.         //----------------------
  103.         void RX8025T_BCD();   //BCD数据转换成两字节        ,RX8025读出的数分离出两字节BCD数
  104.         
  105.          //---------------------------------

  106.          void LCD1602ZL();  //LCD1602指令写入函数
  107.            void LCD1602SZ();  //LCD1602数据写入函数
  108.          void LCD1602CCH();  //LCD1602初始化函数
  109.          void LCD1602SC();        //LCD1602全屏写入函数

  110.         //------------------------------------------------------
  111.                 void I2C_RX();   //I2C多字节读出,1到16字节
  112.         void I2C_TX();   //I2C多字节写入,1到16字节
  113.         //--------------------------------------------------
  114.           void rx8025t_RX();   //RX8025T读出函数
  115.           void rx8025t_TX();   //RX8025T写入函数
  116.            void I2C_1_CLR();   //缓存数据清除

  117.          void delay_ms(unsigned int ms);                                        //函数声明        ,延时函数
  118.           void Delay60us();         //60us延时,用于LCD1602写入数据
  119.           void SecJC();         //定时执行操作(里面嵌套需要定期执行操作的函数,最短定期时间是1ms)


  120.          #define   MAIN_Fosc   11059200L   //定义主时钟,  自定义变量 ,L是长整型的意思   这段代码源自 STC官网例程


  121.          void main()
  122.         {

  123.     P0M0=0x00;
  124.         P0M1=0x00;
  125.     P1M0=0x00;
  126.         P1M1=0x00;
  127.     P2M0=0x00;
  128.         P2M1=0x00;
  129.     P3M0=0x00;
  130.         P3M1=0x00;
  131.     P5M0=0x00;
  132.         P5M1=0x00;
  133.          OUT1=0;
  134.      BUZ=1;
  135.          LED_P31=1;
  136.      AUXR |= 0x04;                //定时器时钟1T模式
  137.         T2L = 0xCD;                //设置定时初值
  138.         T2H = 0xD4;                //设置定时初值
  139.         AUXR |= 0x10;                //定时器2开始计时
  140.         IE2 = 0x04;         
  141.         P_SW2 =0x80;                //D7位控制访问扩展SFR特殊寄存器        ,D4 D5位控制选用某端口做I2C的SCL SDA
  142.         //I2C初始设置
  143.          I2CCFG=0xE0;   // I2C允许和速度控制寄存器
  144.          I2CMSST=0x00;

  145.         LCD1602CCH();                //LCD1602初始化
  146.         
  147.     EA = 1; //中断使能        
  148.         
  149.          //主函数//********************
  150.         while (1)       //下面重复循环
  151.         {

  152.           SecJC();        //计数和BCD转换函数         
  153.            LCD1602SC();           //LCD1602全屏写入函数
  154.            LCD_SC1();     //数据显示程序 1
  155.            keycl();         //按键处理函数
  156.          
  157.           }
  158.           }
  159.          ////////////////***********************

  160.           /*计数*/

  161.          void SecJC()         //定时执行操作(里面嵌套需要定期执行操作的函数,最短定期时间是1ms)
  162.          {
  163.          static unsigned int cnt = 0;   // 1ms计数到1秒
  164.          static unsigned long nsec = 9999;   // 秒计数
  165.          if(fabc1==1)
  166.          {
  167.          fabc1 =0;   //清计数标志

  168.          cnt++;
  169.         if(cnt>=100)
  170.         {
  171.             cnt=0;
  172.            nsec--;                                        //段用于测试和显示正在计时
  173.                          LCD1602RAM1[1][3] = (nsec%10)+0x30;                //个位
  174.                 LCD1602RAM1[1][2] = (nsec/10%10)+0x30;           //十位
  175.                 LCD1602RAM1[1][1] = (nsec/100%10)+0x30;         //百位
  176.                 LCD1602RAM1[1][0] = (nsec/1000%10)+0x30;         //千位
  177.           if(SWJC1==0)                 //          ---只有设置键没按下时才读出时钟数
  178.           {
  179.             rx8025t_RX();   //RX8025T读出函数  
  180.                RX8025T_BCD();        //RX8025T时钟BCD数据转换成两字节
  181.            }
  182.           }
  183.           nsec1++;    //用于闪烁显示的计数
  184.           if(nsec1>800)
  185.           {
  186.                 nsec1=0;
  187.                 }
  188.                 }
  189.                 }

  190.                 //* 定时器0中断服务函数 */
  191.                 void InterruptTimer2() interrupt 12
  192.                 {

  193.         fabc1=1;   //设置计数标志为1
  194.                  keysm();   //按键扫描函数
  195.                
  196.                     }

  197.           //************************************以下是按键程序**************************************
  198.                  ///////////////////////////////////////////////////////

  199.           //按键扫描函数        1行7个键 【按键扫描和处理函数参照书本《手把手教你学51单片机-C语言版》清华大学出版社, 第119页】


  200.           void keysm()
  201.           {
  202.           unsigned char i;
  203.           unsigned char push1;   //暂时存放按键端口此前的值

  204.          
  205.           static unsigned char xdata keybuf[7] = {   //1行7个键 7个缓冲字节
  206.                         0xff,0xff,0xff,0xff,0xff,0xff,0xff};
  207.                         
  208.            SWEN=0;
  209.            push1=P3;          //暂时保存P3口原来的值  ,这里用P3口作按键扫描输入
  210.            P3=0xff;
  211.                
  212.                   
  213.                                 //将一行的8个键值移入缓冲区
  214.                 keybuf[0]=(keybuf[0]<<1)|sw1;
  215.                 keybuf[1]=(keybuf[1]<<1)|sw2;
  216.                 keybuf[2]=(keybuf[2]<<1)|sw3;
  217.                 keybuf[3]=(keybuf[3]<<1)|sw4;
  218.                 keybuf[4]=(keybuf[4]<<1)|sw5;
  219.                 keybuf[5]=(keybuf[5]<<1)|sw6;
  220.                 keybuf[6]=(keybuf[6]<<1)|sw7;           

  221.                 //消抖和更新键值

  222.                 for(i=0; i<7;i++)          //每行7个键
  223.                 {
  224.                 if((keybuf[i] & 0x0f) == 0x00)        //移入的键值 与  0x0f,如果是4次都是0(按下),那就是0x00输出
  225.                 {                                                                                //如果4次都是1,那就是没按下或弹上。
  226.                 kkeysta[i] = 0;
  227.                                                                                                  //如果其他值,那就是有抖动
  228.            }
  229.            else if((keybuf[i] & 0x0f) == 0x0f)
  230.            {
  231.            kkeysta[i] = 1;
  232.                                                                                     //每个键的实时情况反映在keysta[行]上,
  233.            }
  234.            }
  235.            P3=push1;    //恢复此前P3的值
  236.            SWEN=1;
  237.             }
  238.          //---------------------------------------------------------------


  239.                          void keycl()           //按键处理函数        【按键扫描和处理函数参照书本《手把手教你学51单片机-C语言版》清华大学出版社, 第119页】

  240.                 {

  241.           static unsigned char xdata backup[7] = {   //1行*7按键值备份的当前状态        
  242.                                             1,1,1,1,1,1,1};                 //加入static是静态局部变量,上电后只执行一次
  243.                
  244.                           //////////sw1         处理程序
  245.                      if(backup[0] != kkeysta[0])         //如果本次按钮值与上一次不同,那执行下一句,否则就跳过到下一组
  246.                 {
  247.                          if(backup[0] == 0)         //如果按键值是0,那就是有按下,那执行一下句操作,
  248.                          {
  249.                      SWJC1--;               //按键减计数,显示闪烁位置右移*************
  250.                          if(SWJC1<0)
  251.                          {SWJC1=6;}
  252.                         
  253.                         
  254.                          }
  255.                         backup[0] = kkeysta[0];   //更新备份
  256.                         }
  257.                         
  258.                         //////////sw2 处理程序

  259.                           if(backup[1] != kkeysta[1])
  260.                 {
  261.                          if(backup[1] == 0)
  262.                          {
  263.                       SWJC1++;               //按键加计数,显示闪烁位置左移*************
  264.                          if(SWJC1>=7)
  265.                          {SWJC1=0;}
  266.                         
  267.                          }
  268.                         backup[1] = kkeysta[1];   //更新备份
  269.                         }

  270.                            //////////sw3 处理程序

  271.                           if(backup[2] != kkeysta[2])
  272.                 {
  273.                          if(backup[2] == 0)
  274.                          {
  275.                      //LED_P31 = ~LED_P31;                           //测试语句  //***这条就是SW3对应执行的内容
  276.                          SWABC1();   //时间数值调整函数
  277.                          }
  278.                         backup[2] = kkeysta[2];   //更新备份
  279.                         }

  280.                
  281.                    //////////sw4   处理程序

  282.                           if(backup[3] != kkeysta[3])
  283.                 {
  284.                          if(backup[3] == 0)
  285.                          {
  286.                      //LED_P31 = ~LED_P31;                           //测试语句  //***这条就是SW3对应执行的内容         
  287.                          SET_RTC();           //设置好的数据保存到RX8025T
  288.                          }
  289.                         backup[3] = kkeysta[3];   //更新备份
  290.                         }
  291.                    //////////sw5  处理程序

  292.                           if(backup[4] != kkeysta[4])
  293.                 {
  294.                          if(backup[4] == 0)
  295.                          {
  296.                      LED_P31 = ~LED_P31;                           //测试语句  //***这条就是SW4对应执行的内容
  297.                         
  298.                          }
  299.                         backup[4] = kkeysta[4];   //更新备份
  300.                         }

  301.                    //////////sw6 处理程序

  302.                           if(backup[5] != kkeysta[5])
  303.                 {
  304.                          if(backup[5] == 0)
  305.                          {
  306.                      LED_P31 = ~LED_P31;                           //LED灯取反   测试语句
  307.                          SWJC1=0;     // SWJC1计数置0,退设置操作

  308.                          }
  309.                         backup[5] = kkeysta[5];   //更新备份
  310.                         }

  311.                         //////////sw7 处理程序

  312.                           if(backup[6] != kkeysta[6])
  313.                 {
  314.                          if(backup[6] == 0)
  315.                          {
  316.                         

  317.                          I2C_1_CLR();     // 缓存数据清除  
  318.                          }

  319.                         backup[6] = kkeysta[6];   //更新备份
  320.                         }

  321.                   

  322.                         //sw7 长按处理程序
  323.                         if(kkeysta[6]==0)
  324.                   {                 
  325.                   SW7_S1=1;  //如果sw7按下那就置位标志作计时用
  326.                   
  327.                    }
  328.                    if(kkeysta[6]==1)
  329.                    {
  330.                         SW7_S1=0;          //如果SW7弹开,那标志关闭
  331.                         SW7_S2=0;     //清除计时
  332.                         //BUZ=1;                //测试语句
  333.                         //LED_P31 =1;          //熄灭LED          测试语句
  334.                         }
  335.                    }

  336.           //---------------------------------------------------------

  337.                 //************************************以上是按键程序********************

  338.                                                    
  339.         

  340.                 void Delay60us()                //@11.0592MHz          60us延时         源自stc-isp软件生成
  341.         {
  342.         unsigned char i, j;

  343.         _nop_();
  344.         i = 1;
  345.         j = 162;
  346.         do
  347.         {
  348.                 while (--j);
  349.         } while (--i);
  350.         }

  351.          void delay_ms(unsigned int ms)       //延时函数,ms,要延时的ms数, 这里只支持1~255ms. 自动适应主时钟.
  352. {                                                             //        延时函数 源自 STC官网例程
  353.      unsigned int i;
  354.      do{
  355.           i = MAIN_Fosc / 13000;
  356.           while(--i)    ;   //14T per loop
  357.      }while(--ms);
  358. }


  359.                          //LCD1602指令写入 *******下面所有LCD1602操作的程序都是梁百万 参照网上前辈的程序重新编写
  360.                         void LCD1602ZL()
  361.                         {
  362.                         LCD_RS=0;
  363.                         LCD_EN=1;
  364.                    LCD_D0=LCD1602RAM2_D0;
  365.                    LCD_D1=LCD1602RAM2_D1;
  366.                    LCD_D2=LCD1602RAM2_D2;
  367.                    LCD_D3=LCD1602RAM2_D3;
  368.                    LCD_D4=LCD1602RAM2_D4;
  369.                    LCD_D5=LCD1602RAM2_D5;
  370.                    LCD_D6=LCD1602RAM2_D6;
  371.                    LCD_D7=LCD1602RAM2_D7;
  372.                     LCD_EN=0;                 //E,下降沿,让LCD读取
  373.                         Delay60us();  //延时80us

  374.                         }

  375.                  //LCD1602数据写入
  376.                         void LCD1602SZ()
  377.                    {
  378.                          LCD_RS=1;
  379.                         LCD_EN=1;
  380.                    LCD_D0=LCD1602RAM2_D0;
  381.                    LCD_D1=LCD1602RAM2_D1;
  382.                    LCD_D2=LCD1602RAM2_D2;
  383.                    LCD_D3=LCD1602RAM2_D3;
  384.                    LCD_D4=LCD1602RAM2_D4;
  385.                    LCD_D5=LCD1602RAM2_D5;
  386.                    LCD_D6=LCD1602RAM2_D6;
  387.                    LCD_D7=LCD1602RAM2_D7;
  388.                     LCD_EN=0;  //E,下降沿,让LCD读取
  389.                          Delay60us();  //延时80us

  390.                         }

  391.                         //LCD1602初始化
  392.                         void LCD1602CCH()
  393.                         {
  394.                         
  395.                         LCD1602RAM2=0;
  396.                         delay_ms(15);          //延时15毫秒
  397.                         LCD1602RAM2=0x38;  //;16行*2,5*8
  398.                         LCD1602ZL();         //写入指令
  399.                    delay_ms(5);          //延时5毫秒
  400.                    LCD1602RAM2=0x38;  //;16行*2,5*8
  401.                         LCD1602ZL();         //写入指令
  402.                    delay_ms(5);          //延时5毫秒
  403.                    LCD1602RAM2=0x08; // 关显示
  404.                    LCD1602ZL();         //写入指令
  405.                    delay_ms(1);          //延时1毫秒
  406.                   LCD1602RAM2=0x01;        //清屏
  407.                    LCD1602ZL();         //写入指令
  408.                    delay_ms(5);          //延时5毫秒
  409.                    LCD1602RAM2=0x06;        //;地址计数器AC自动加1,光标右移 *******
  410.                    delay_ms(1);          //延时1毫秒
  411.                    LCD1602RAM2=0x0C;        //开显示
  412.                   LCD1602ZL();         //写入指令
  413.                    delay_ms(1);          //延时1毫秒
  414.                   
  415.                    }


  416.                  //------------------------------------------------------------------------

  417.                   
  418.               void LCD_SC1()     //全屏显示数据写入程序         把RX8025T分离出来后的BCD数据送到显示缓存,
  419.                      {                                //跟着在显示程序void LCD1602SC()那写入到显示屏
  420.                         LCD1602RAM1[0][0] ='2';                          //年的2
  421.                                 LCD1602RAM1[0][1] ='0';   //年的0

  422.                         LCD1602RAM1[0][2] =YEAR10 + 0x30;  //年十位
  423.                                 LCD1602RAM1[0][3] =YEAR1 + 0x30;  //年个位
  424.                                  
  425.                                 LCD1602RAM1[0][4] =        '/';                  //分隔符

  426.                         LCD1602RAM1[0][5] =MONTH10 + 0x30;  //月十位
  427.                                 LCD1602RAM1[0][6] =MONTH1 + 0x30;  //月个位

  428.                                 LCD1602RAM1[0][7] ='/';                  //分隔符

  429.                         LCD1602RAM1[0][8] =DAY10 + 0x30;  //日十位
  430.                                 LCD1602RAM1[0][9] =DAY1 + 0x30;  //日个位

  431.                                 LCD1602RAM1[0][10] ='/';                  //分隔符

  432.                         LCD1602RAM1[0][11] =HOUR10 + 0x30;  //时十位
  433.                                 LCD1602RAM1[0][12] =HOUR1 + 0x30;  //时个位  

  434.                                 LCD1602RAM1[0][13] =':';                  //分隔符

  435.                         LCD1602RAM1[0][14] =MIN10 + 0x30;  //分十位            
  436.                                 LCD1602RAM1[0][15] =MIN1+0x30;  //分个位


  437.                         //LCD1602RAM1[1][0] =1+0X30;
  438.                                 //LCD1602RAM1[1][1] =1+0X30;

  439.                        // LCD1602RAM1[1][2] =        1+0X30;
  440.                           //LCD1602RAM1[1][3] =        1+0X30;
  441.                                  
  442.                                 LCD1602RAM1[1][4] =        0X20;

  443.                         LCD1602RAM1[1][5] =0X20;
  444.                                 LCD1602RAM1[1][6] =0X20;

  445.                                 LCD1602RAM1[1][7] =        0X20;

  446.                         LCD1602RAM1[1][8] = 0X20;
  447.                                 LCD1602RAM1[1][9] =        0X20;

  448.                                 LCD1602RAM1[1][10] = 0X20;

  449.                         LCD1602RAM1[1][11] = 0X20;

  450.                                 LCD1602RAM1[1][12] =0X20;
  451.                                 LCD1602RAM1[1][13] =0X20;
  452.                         LCD1602RAM1[1][14] =SEC10+0X30;  //秒十位
  453.                

  454.                                 LCD1602RAM1[1][15] =SEC1+0X30;  //秒个位

  455.                                 SCXL();    //LCD闪烁显示操作        //        调用大于0.6秒就对应键计数给对应缓存填上0X20
  456.                              }


  457.                           void I2C_1_CLR()   //缓存数据清除
  458.                           {
  459.                            unsigned char i=8;

  460.                           while(i--)
  461.                           { I2C_1[i]=0x00;         }
  462.                            }
  463.                          //---------------------------------------------------------------

  464.                         // LCD1602全屏显示程序,16字*2行

  465.                   void LCD1602SC()
  466.                    {
  467.                    unsigned char i=16;          //每行的个数计数
  468.                    unsigned char x=0;                 //行数
  469.                    unsigned char y=0;                //列数
  470.                   
  471.                    LCD1602RAM2=0x80;   //这个是LCD第1行的地址
  472.                    LCD1602ZL(); //以地址/指令形式发送到LCD1602

  473.                    while(i--)
  474.                    {
  475.                    LCD1602RAM2=LCD1602RAM1[0][y];
  476.                    LCD1602SZ(); //以数据形式发送到LCD1602
  477.                    y++;
  478.                    };

  479.                LCD1602RAM2=0xC0;   //这个是LCD第2行的地址
  480.                    LCD1602ZL(); //以地址/指令形式发送到LCD1602
  481.                    i=16        ;                 //每行的个数计数
  482.                    y=0;        //每行的个数
  483.                    while(i--)
  484.                    {
  485.                    LCD1602RAM2=LCD1602RAM1[1][y];
  486.                    LCD1602SZ(); //以数据形式发送到LCD1602
  487.                    y++;
  488.                    };
  489.                    }           

  490.                 //----------------------------------------------

  491.                  void SCXL()    //LCD闪烁显示操作          用于设置时某位的显示闪烁
  492.                    {
  493.                    if(SWJC1>=1)
  494.                    {
  495.                         if(nsec1>600)          //大于0.6秒就在对应位置空格  SWJC1中设置按键对应数
  496.                         {
  497.                         if(SWJC1==1)
  498.                         {
  499.                         LCD1602RAM1[0][15]=0x20;
  500.                         }

  501.                         if(SWJC1==2)
  502.                         {
  503.                         LCD1602RAM1[0][14]=0x20;
  504.                         }
  505.                         
  506.                         if(SWJC1==3)
  507.                         {
  508.                         LCD1602RAM1[0][12]=0x20;
  509.                         LCD1602RAM1[0][11]=0x20;
  510.                         }
  511.                         if(SWJC1==4)
  512.                         {
  513.                         LCD1602RAM1[0][9]=0x20;
  514.                         LCD1602RAM1[0][8]=0x20;
  515.                         }
  516.                         if(SWJC1==5)
  517.                         {
  518.                         LCD1602RAM1[0][6]=0x20;
  519.                         LCD1602RAM1[0][5]=0x20;
  520.                         }
  521.                         if(SWJC1==6)
  522.                         {
  523.                         LCD1602RAM1[0][3]=0x20;
  524.                         LCD1602RAM1[0][2]=0x20;
  525.                         }

  526.                          else;
  527.                         }
  528.                         }
  529.                         }

  530.                    //--------------------------------------------------------

  531.            //   硬件I2C串口        程序        参照STC官方文档有关I2C硬件操作的程序,由梁百万重新编写
  532.                                                    //下面的I2C读写函数可以读写8位地址的器件,如24C01~24C16, DS1307,RX8025T
  533.            //变量说明
  534.             //unsigned char xdata I2C_ADDR1     ;从器件的硬件地址
  535.                 //unsigned char xdata I2C_ADDR2     ;从器件的数据地址首址
  536.                 //unsigned char xdata I2C_X;    数据每次存放或取出的字节数,1到256字节
  537.                 //unsigned char xdata I2C_i; //主器件缓存的数据地址首址        (1维数组的个数计数变量)
  538.                 //unsigned char xdata I2C_1[16]        // 主器件缓存 ,用变量I2C_i作位置计数
  539.         
  540.                    //I2C多字节写入,1到16字节

  541.                  void I2C_TX()   //I2C多字节写入,1到16字节
  542.                 {
  543.                  I2C_i=0;        //主器件缓存的数据地址首址
  544.                              //第1步,起始+发送硬件地址+接收ACK
  545.                   I2CTXD=I2C_ADDR1; //从器件的硬件地址
  546.                   I2CMSCR=0x09;  //此命令是 START+SDATA+ACK
  547.                   
  548.                   while (!(I2CMSST & 0x40));   //检查是否发送完成
  549.           I2CMSST &= ~0x40;

  550.                       //第2步,发送从器件的数据地址首址+接收ACK
  551.                    I2CTXD=I2C_ADDR2;   //从器件的数据地址首址
  552.                    I2CMSCR=0x0a;   //此命令是SDATA+ACK
  553.                            
  554.                    while (!(I2CMSST & 0x40));  //检查是否发送完成
  555.            I2CMSST &= ~0x40;

  556.                  while(I2C_X--)          //第3步,主器件的缓存上写入多个数据到从器件
  557.                  {
  558.                    I2CTXD=I2C_1[I2C_i];//主器件缓存的数据地址首址
  559.                    I2CMSCR=0x0a;   //此命令是SDATA+ACK
  560.                            
  561.                    while (!(I2CMSST & 0x40));        //检查是否发送完成
  562.            I2CMSST &= ~0x40;        
  563.                    I2C_i++;   //主器件缓存的数据地址加1
  564.                   }
  565.                         //第4步,发送停止信号命令
  566.                   I2CMSCR=0x06;   //停止信号命令
  567.                   
  568.                   while (!(I2CMSST & 0x40));  //检查是否发送完成
  569.           I2CMSST &= ~0x40;
  570.           I2CMSST &= ~0x40;  
  571.                   }

  572.                   //--------------------------------------------------

  573.                    //I2C多字节读出,1到16字节

  574.                   void I2C_RX()   //I2C多字节读出,1到16字节
  575.                   {
  576.                   
  577.                   I2C_i=0;        //主器件缓存的数据地址首址
  578.                   
  579.                       //第1步,起始+发送硬件地址+接收ACK
  580.                  I2CTXD=I2C_ADDR1; //从器件的硬件地址
  581.                  I2CMSCR=0x09;  //此命令是 START+SDATA+ACK
  582.                   while (!(I2CMSST & 0x40)); //检查是否发送完成
  583.           I2CMSST &= ~0x40;
  584.                   
  585.                              //第2步,发送从器件的数据地址首址+接收ACK
  586.                    I2CTXD=I2C_ADDR2;   //从器件的数据地址首址
  587.                    I2CMSCR=0x0a;   //此命令是SDATA+ACK
  588.                            
  589.                    while (!(I2CMSST & 0x40));  //检查是否发送完成
  590.            I2CMSST &= ~0x40;

  591.                   I2C_ADDR1++;  //对硬件地址由写入改成读出,  地址数据D0位是1为读,0为写
  592.                                //第3步,再次发送,起始+发送硬件地址 读+接收ACK
  593.                   I2CTXD=I2C_ADDR1; //从器件的硬件地址
  594.                   I2CMSCR=0x09;  //此命令是 START+SDATA+ACK
  595.                  
  596.                   while (!(I2CMSST & 0x40));   //检查是否发送完成
  597.           I2CMSST &= ~0x40;

  598.                   while(I2C_X--)          //第4步,读出多个数据并存放到缓存上
  599.                  {
  600.                   I2CMSCR=0x0b; //此命令是 接收数据+发送ACK
  601.                   while (!(I2CMSST & 0x40)); //检查是否发送完成
  602.           I2CMSST &= ~0x40;

  603.                   I2C_1[I2C_i]=I2CRXD        ;  //读出后要传送到需要的寄存器
  604.                   I2C_i++;   //主器件缓存的数据地址加1
  605.                   }
  606.                                  //第5步,发出非应答信号NACK,
  607.                    I2CMSCR=0x0c; //此命令是 接收数据+发送NACK
  608.                            
  609.                    while (!(I2CMSST & 0x40));        //检查是否发送完成
  610.            I2CMSST &= ~0x40;

  611.                           //第6步,停止
  612.                   I2CMSCR=0x06;   //停止信号命令
  613.                   while (!(I2CMSST & 0x40)); //检查是否发送完成
  614.           I2CMSST &= ~0x40;
  615.                   }

  616.                  //--------------------------------------------------------


  617.                     void rx8025t_RX()                //RX8025T读出函数
  618.                       {
  619.                             I2C_ADDR1=0x64;    // RX8025T硬件地址0x64, 24C04地址0ACH
  620.                             I2C_ADDR2=0x00;          //从器件需要读出的地址首址
  621.                             I2C_X=8;                         //需要读出的字节数
  622.                             I2C_i=0x00;   //缓存首址
  623.                             I2C_RX();         //读出数据
  624.                             }



  625.                    void rx8025t_TX()   //RX8025T写入函数
  626.                       {
  627.                             I2C_ADDR1=0x64;    // RX8025T硬件地址0x64, 24C04地址0ACH
  628.                        I2C_ADDR2=0x00;          //从器件需要写入的地址首址
  629.                             I2C_X=8;                         //需要写入的字节数
  630.                             I2C_i=0x00;   //缓存首址
  631.                             I2C_TX();         //写入数据
  632.                             }


  633.                    void RX8025T_BCD()        //BCD数据转换成两字节
  634.                   {
  635.                    SEC1=(I2C_1[0]) & 0x0f;        //取秒个位值
  636.                    SEC10=(I2C_1[0] & 0xf0)/16;           //取秒十位值
  637.                    MIN1=(I2C_1[1]) & 0x0f;        //取分个位值
  638.                    MIN10=(I2C_1[1] & 0xf0)/16;        //取分十位值
  639.                    HOUR1=(I2C_1[2]) & 0x0f;        //取时个位值
  640.                    HOUR10=(I2C_1[2] & 0xf0)/16;//取时十位值
  641.                    DAY1=(I2C_1[4]) & 0x0f;        //取日个位值
  642.                    DAY10=(I2C_1[4] & 0xf0)/16;        //取日十位值
  643.                    MONTH1=(I2C_1[5])& 0x0f;        //取月个位值
  644.                    MONTH10=(I2C_1[5]& 0xf0)/16;        //取月十位值
  645.                    YEAR1=(I2C_1[6])& 0x0f;        //取年个位值
  646.                    YEAR10=(I2C_1[6]& 0xf0)/16;        //取年个位值
  647.                    }




  648.                 //---------------------------------

  649.                  //SWJC1 ,不为0时是设置键有按下,才能作加数操作

  650.                 void SWABC1()   //时间数值调整函数
  651.            {
  652.                 if(SWJC1 != 0)          //SWJC1 ,不为0,也就是左右移位有按下时才能加数操作
  653.                 {
  654.                 if(SWJC1 == 1)           //分个位调整
  655.                 {
  656.                  MIN1++;                 //分个位加1
  657.                  if(MIN1>=10)
  658.                  {
  659.                  MIN1=0;
  660.                  }
  661.                  }
  662.                 if(SWJC1 == 2)           //分十位调整
  663.                 {
  664.                  MIN10++;
  665.                 if(MIN10>=6)
  666.                 {
  667.                 MIN10=0;
  668.                 }
  669.                 }
  670.                 if(SWJC1 == 3)           //小时位调整
  671.                 {
  672.                  HOUR1++;
  673.                  if(HOUR1>=10)
  674.                  {
  675.                  HOUR10++;
  676.                  HOUR1=0;
  677.                  }
  678.                  if(((HOUR10*10) + HOUR1) >= 24)   //计算个位和十位总数是否大于24小时
  679.                  {
  680.                  HOUR10=0;
  681.                  HOUR1=0;
  682.                  }
  683.                  }
  684.                  //---------------------------------------------------------------//
  685.                  if(SWJC1 == 4)           //日数调整                                                                        
  686.                  {                                                                                                                     
  687.                  DAY1++;                                                                                                               
  688.                  if(DAY1>=10)                                                                                                        
  689.                  {                                                                                                                                 
  690.                   DAY10++;                                                                                                                 
  691.                   DAY1=0;                                                                                                                  
  692.                   }                                                                                                                                 
  693.                   //--------------------日数设置对应月数最大值的计算                          
  694.                   switch((MONTH10*10)+MONTH1)                                                                       
  695.                   {                                                                                                                                 
  696.                   case 1:if(((DAY10*10)+DAY1)>=32) {DAY10=0;DAY1=1;} break;                  
  697.                   case 3:if(((DAY10*10)+DAY1)>=32) {DAY10=0;DAY1=1;} break;               
  698.                   case 5:if(((DAY10*10)+DAY1)>=32) {DAY10=0;DAY1=1;} break;               
  699.                   case 7:if(((DAY10*10)+DAY1)>=32) {DAY10=0;DAY1=1;} break;                 
  700.                   case 8:if(((DAY10*10)+DAY1)>=32) {DAY10=0;DAY1=1;} break;                  
  701.                   case 10:if(((DAY10*10)+DAY1)>=32) {DAY10=0;DAY1=1;} break;        
  702.                   case 12:if(((DAY10*10)+DAY1)>=32) {DAY10=0;DAY1=1;} break;         
  703.                   case 4:if(((DAY10*10)+DAY1)>=31) {DAY10=0;DAY1=1;} break;            
  704.                   case 6:if(((DAY10*10)+DAY1)>=31) {DAY10=0;DAY1=1;} break;               
  705.                   case 9:if(((DAY10*10)+DAY1)>=31) {DAY10=0;DAY1=1;} break;                 
  706.                   case 11:if(((DAY10*10)+DAY1)>=31) {DAY10=0;DAY1=1;} break;        
  707.                   case 2: if(((YEAR10*10)+YEAR1)%4 ==0)                                                         
  708.                   {                                                                                                                                 
  709.                   if(((DAY10*10)+DAY1) >= 30)         //闰年,那2月有29天                       
  710.                     {                                                                                                                        
  711.                         DAY10=0;DAY1=1;                                                                                             
  712.                         }                                                                                                                       
  713.                         }                                                                                                                       
  714.                         if(((YEAR10*10)+YEAR1)%4 !=0)                                                               
  715.                         {                                                                                                            
  716.                     if(((DAY10*10)+DAY1) >= 29)   //非闰年,那2月有28天                        
  717.                     {                                                                                                                       
  718.                      DAY10=0;DAY1=1;                                                                                         
  719.                          }                                                                                                                        
  720.                          }                                                                                                                          
  721.                            break;                                                                                         
  722.                                                                                                                                              
  723.                   default:break;                                                                                                
  724.                      }                                                                                                                  
  725.                    //-------------------------------                                                        
  726.                   }                                                                                                                                
  727.                    //--------------------------------------------------------------

  728.                   if(SWJC1 == 5)           //月数调整
  729.                   {
  730.                    MONTH1++;
  731.                    if(MONTH1>=10)
  732.                    {
  733.                    MONTH10++;
  734.                    MONTH1=0;
  735.                    }
  736.                    if(((MONTH10*10)+MONTH1) >= 13)
  737.                    {
  738.                    MONTH10=0;
  739.                    MONTH1=1;
  740.                    }
  741.                   switch((MONTH10*10)+MONTH1)                                                                          
  742.                   {                                                                                                                                 
  743.                   case 4:if(((DAY10*10)+DAY1)>=31) {DAY10=3;DAY1=0;} break;      // 如果月数调整到是4.6.9.11,那要回头计算日数是否大于30
  744.                   case 6:if(((DAY10*10)+DAY1)>=31) {DAY10=3;DAY1=0;} break;               
  745.                   case 9:if(((DAY10*10)+DAY1)>=31) {DAY10=3;DAY1=0;} break;                  
  746.                   case 11:if(((DAY10*10)+DAY1)>=31) {DAY10=3;DAY1=0;} break;        
  747.                   case 2: if(((YEAR10*10)+YEAR1)%4 ==0)                                                      
  748.                   {                                                                                                                                
  749.                   if(((DAY10*10)+DAY1) >= 30)         //闰年,那2月有29天   //如果月数调整到是2月,那要回头计算日数是否大于28/29
  750.                     {                                                                                                                        
  751.                         DAY10=2;DAY1=9;                                                                                                
  752.                         }                                                                                                                        
  753.                         }                                                                                                                        
  754.                         if(((YEAR10*10)+YEAR1)%4 !=0)                                                               
  755.                         {                                                                                                            
  756.                     if(((DAY10*10)+DAY1) >= 29)   //非闰年,那2月有28天                        
  757.                     {                                                                                                                       
  758.                      DAY10=2;DAY1=8;                                                                                    
  759.                          }                                                                                                                       
  760.                          }                                                                                                                        
  761.                            break;                                                                                      
  762.                                                                                                                                              
  763.                   default:break;                                                                                               
  764.                      }        
  765.                    }
  766.                    //----------------
  767.                    if(SWJC1 == 6)           //年数调整  
  768.                    {
  769.                    YEAR1++;
  770.                    if(YEAR1>=10)
  771.                    {
  772.                    YEAR10++;
  773.                    YEAR1=0;
  774.                    if(YEAR10>=10)
  775.                    {
  776.                    YEAR10=0;
  777.                    }
  778.                    }
  779.                    if(((YEAR10*10)+YEAR1)%4 !=0)          //如设置是非闰年,那要回头看看和处理2月份的日数是否大于28
  780.                    {                                                                                                                                                                                                                                                                                        //
  781.                     if(((DAY10*10)+DAY1) >= 29)   //非闰年,那2月有28天                          
  782.                     {                                                                                                                     
  783.                      DAY10=2;DAY1=8;                                                                                         
  784.                          }                                                                                                                        
  785.                          }
  786.                         }
  787.                    //-----------------------------------------
  788.                   }

  789.                  }
  790.                

  791.                  void SET_RTC()           //设置好的数据保存到RX8025T
  792.                  {
  793.                   if(SWJC1 != 0)         //需要在只有按下过数值设置时才把数值存回到RX8025T
  794.                   {
  795.                   I2C_1[1] = ((MIN10*16) + MIN1);                //把两个BCD数合并成一个字节
  796.                   I2C_1[2] = ((HOUR10*16) + HOUR1);
  797.                   I2C_1[4] = ((DAY10*16) + DAY1);
  798.                   I2C_1[5] = ((MONTH10*16) + MONTH1);
  799.                   I2C_1[6] = ((YEAR10*16) + YEAR1);
  800.                   I2C_1[0] =0;
  801.                   rx8025t_TX();   //RX8025T写入函数
  802.                   SWJC1=0;    //存放好数据后就退出设置
  803.                   }
  804.                   else;
  805.                   }

复制代码

  

打赏

参与人数 1家元 +10 收起 理由
guangqu + 10

查看全部打赏

 楼主| 发表于 2021-6-18 20:06:23 | 显示全部楼层
本帖最后由 广东梁百万 于 2021-6-18 20:12 编辑

-------------------------

回复 支持 反对

使用道具 举报

发表于 2021-6-18 20:19:26 | 显示全部楼层
:praise:厉害了,楼主推荐一下相关书籍吧,看看能不能学了
回复 支持 反对

使用道具 举报

发表于 2021-6-18 20:32:33 来自手机浏览器 | 显示全部楼层
啰嗦点倒是不怕,关键是这结构…老哥这C语言和汇编不太一样,这种写法叫做main神……不是不能用就是不规范啊……虽然我刚开始的时候也是这么写的……
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-6-18 20:41:24 | 显示全部楼层
触景情伤 发表于 2021-6-18 20:32
啰嗦点倒是不怕,关键是这结构…老哥这C语言和汇编不太一样,这种写法叫做main神……不是不能用就是不规范 ...

新手,能写出来对我来说已是很满足了,张就下:lol:
回复 支持 反对

使用道具 举报

发表于 2021-6-18 20:53:31 来自手机浏览器 | 显示全部楼层
广东梁百万 发表于 2021-6-18 20:41
新手,能写出来对我来说已是很满足了,张就下

新手?我熟悉的也就你和那个杨小强什么的能撸汇编……
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-6-18 21:06:16 | 显示全部楼层
触景情伤 发表于 2021-6-18 20:53
新手?我熟悉的也就你和那个杨小强什么的能撸汇编……

论坛里的汇编大神很多滴
回复 支持 反对

使用道具 举报

发表于 2021-6-19 07:05:42 | 显示全部楼层
触景情伤 发表于 2021-6-18 20:53
新手?我熟悉的也就你和那个杨小强什么的能撸汇编……

@hit00 版主也是汇编牛人
回复 支持 反对

使用道具 举报

发表于 2021-6-19 08:58:46 来自手机浏览器 | 显示全部楼层
guangqu 发表于 2021-6-19 07:05
@hit00 版主也是汇编牛人

说真的这些个版主啥的我还真不怎么熟悉,或者说不知道谁是版主…
回复 支持 反对

使用道具 举报

发表于 2021-6-19 11:15:08 | 显示全部楼层
满满的汇编风
回复 支持 反对

使用道具 举报

发表于 2021-6-19 21:36:04 | 显示全部楼层
能做个LED就好了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-6-19 22:13:43 | 显示全部楼层

我一开始就是汇编起步的,估计以后改不了这个风格
回复 支持 反对

使用道具 举报

 楼主| 发表于 2021-6-20 23:06:05 | 显示全部楼层
gdszyrx 发表于 2021-6-19 21:36
能做个LED就好了

今晚在考虑一个LED显示的,带倒计时功能,用在厨房里, 暂时设想是 用4位*2行显示,第一行显示倒计时,第二行显示实时时间。用EC11旋转编码器调时间。
回复 支持 反对

使用道具 举报

发表于 2023-9-12 10:33:15 | 显示全部楼层
程序我复制编译了一下,没报错。我打算研究一下RX8025T的用法。谢谢楼主分享!
回复 支持 1 反对 0

使用道具 举报

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

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2024-5-2 03:04 , Processed in 0.156000 second(s), 14 queries , Redis On.

Powered by Discuz!

© 2006-2023 smzj.net

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