|
这个电路原本设计是给一台机器作控制用途,下面的代码是其中计时部分,单片机是STC8G1K17+RX8025T+LCD1602
我以前是学汇编语言的,今年开始学C语言,
下面程序是我在学习过程中不断修改积累下来的,程序里存在一些是测试用途的代码, 程序里参照和用到他人的代码在注释那作了说明
我新手的,写得很啰嗦,希望指教。
-
- #include<stc8g.h>
- #include "intrins.h"
- sbit sw1 = P3^1;
- sbit sw2 = P3^2;
- sbit sw3 = P3^3;
- sbit sw4 = P3^4;
- sbit sw5 = P3^5;
- sbit sw6 = P3^6;
- sbit sw7 = P3^7;
-
- sbit SWEN = P1^6; //按键选通口
- sbit LED_P31 = P3^1; // 低电平发亮
- sbit RUN_TST= P5^4; //检测输入,低电平时确认有测试动作
- sbit OUT1 = P5^5; //第1路输出 高电平时接通
- sbit BUZ = P3^0; //报警输出,为0时有响声
- sbit POW_TST = P1^7; //电压过低检测输入,输入为低电平时即电压过低
- sbit LCD_D0 = P1^2;
- sbit LCD_D1 = P1^3 ;
- sbit LCD_D2 = P3^2 ;
- sbit LCD_D3 = P3^3 ;
- sbit LCD_D4 = P3^4 ;
- sbit LCD_D5 = P3^5 ;
- sbit LCD_D6 = P3^6 ;
- sbit LCD_D7 = P3^7;
- sbit LCD_RS = P1^0; //LCD1602 的 RS端 ,1-数据,0-指令
- sbit LCD_EN = P1^1 ; //LCD1602 的 E端 ,先从低变高,再变低,以确认输入数据或命令
- //-----------------------------------------------------------------------------------------
- //iic串口控制寄存器定义 **********下面宏定义来自STC官网的例程
-
- #define I2CCFG (*(unsigned char volatile xdata *)0xfe80) // #define又称宏定义,标识符为所定义的宏名,简称宏。
- #define I2CMSCR (*(unsigned char volatile xdata *)0xfe81) //volatile的本意是“易变的”
- #define I2CMSST (*(unsigned char volatile xdata *)0xfe82)
- #define I2CSLCR (*(unsigned char volatile xdata *)0xfe83)
- #define I2CSLST (*(unsigned char volatile xdata *)0xfe84)
- #define I2CSLADR (*(unsigned char volatile xdata *)0xfe85)
- #define I2CTXD (*(unsigned char volatile xdata *)0xfe86)
- #define I2CRXD (*(unsigned char volatile xdata *)0xfe87)
- #define I2CMSAUX (*(unsigned char volatile xdata *)0xfe88)
- sbit SDA = P1^4;
- sbit SCL = P1^5;
- unsigned char xdata I2C_ADDR1; //I2C从器件的硬件地址存放点
- unsigned char xdata I2C_ADDR2; //I2C从器件的数据地址首址存放点
- unsigned char xdata I2C_X; //I2C数据每次存放或取出个数,最大16字节
- unsigned char xdata I2C_i=0; //主器件的数据地址首址
- //--------------------------------------------------------------------------
- #define ADCTIM (*(unsigned char volatile xdata *)0xfea8) //ADC转换控制寄存器定义
-
-
- unsigned char xdata LCD1602RAM1[2][16]={
- {0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20}, //LCD1602的缓存,初始值是空格20H
- {0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20}
- };
-
- unsigned char xdata I2C_1[64]={ //I2C读或写的临时缓存
- 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
- 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
- 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
- 0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
- };
- //**************************************************************************
- unsigned char xdata kkeysta[7] ={ //全部按键的当前状态
- 1,1,1,1,1,1,1,
- };
- signed char xdata SWJC1=0; //用于按键位置计数,带符号整形,用以小于0的计数判断
- //---------------------时间存放 每个变量存放一个BCD数
- unsigned char xdata SEC1; //秒个位
- unsigned char xdata SEC10; //秒十位
- unsigned char xdata MIN1=0; //分个位
- unsigned char xdata MIN10; //分十位
- unsigned char xdata HOUR1; //时个位
- unsigned char xdata HOUR10; //时十位
- unsigned char xdata DAY1; //日个位
- unsigned char xdata DAY10; //日十位
- unsigned char xdata MONTH1; //月个位
- unsigned char xdata MONTH10; //月十位
- unsigned char xdata YEAR1; //年个位
- unsigned char xdata YEAR10; //年十位
- //-----------------------------------------------
- unsigned char bdata LCD1602RAM2; //LCD1602的写入缓冲
- sbit LCD1602RAM2_D0= LCD1602RAM2^0;
- sbit LCD1602RAM2_D1= LCD1602RAM2^1;
- sbit LCD1602RAM2_D2= LCD1602RAM2^2;
- sbit LCD1602RAM2_D3= LCD1602RAM2^3;
- sbit LCD1602RAM2_D4= LCD1602RAM2^4;
- sbit LCD1602RAM2_D5= LCD1602RAM2^5;
- sbit LCD1602RAM2_D6= LCD1602RAM2^6;
- sbit LCD1602RAM2_D7= LCD1602RAM2^7;
- unsigned int xdata nsec1=0; //用于闪烁显示的时间计数
-
- unsigned char fabc1 = 0; //计数标志
- unsigned char xdata SW7_S1=0; //按键SW7的长按标志1
- unsigned int xdata SW7_S2=0; //按键SW7的长按计时
- //-------------------------------------------------------------
- void keysm(); //按键扫描函数
- void keycl(); //按键处理函数
- void SWABC1(); //时间数值调整函数
- void SET_RTC(); //设置好的数据保存到RX8025T
- //**************************************************************************
- void LCD_SC1(); ////全屏显示数据写入程序
- void SCXL(); //LCD闪烁显示操作
- //----------------------
- void RX8025T_BCD(); //BCD数据转换成两字节 ,RX8025读出的数分离出两字节BCD数
-
- //---------------------------------
- void LCD1602ZL(); //LCD1602指令写入函数
- void LCD1602SZ(); //LCD1602数据写入函数
- void LCD1602CCH(); //LCD1602初始化函数
- void LCD1602SC(); //LCD1602全屏写入函数
- //------------------------------------------------------
- void I2C_RX(); //I2C多字节读出,1到16字节
- void I2C_TX(); //I2C多字节写入,1到16字节
- //--------------------------------------------------
- void rx8025t_RX(); //RX8025T读出函数
- void rx8025t_TX(); //RX8025T写入函数
- void I2C_1_CLR(); //缓存数据清除
- void delay_ms(unsigned int ms); //函数声明 ,延时函数
- void Delay60us(); //60us延时,用于LCD1602写入数据
- void SecJC(); //定时执行操作(里面嵌套需要定期执行操作的函数,最短定期时间是1ms)
- #define MAIN_Fosc 11059200L //定义主时钟, 自定义变量 ,L是长整型的意思 这段代码源自 STC官网例程
- void main()
- {
- P0M0=0x00;
- P0M1=0x00;
- P1M0=0x00;
- P1M1=0x00;
- P2M0=0x00;
- P2M1=0x00;
- P3M0=0x00;
- P3M1=0x00;
- P5M0=0x00;
- P5M1=0x00;
- OUT1=0;
- BUZ=1;
- LED_P31=1;
- AUXR |= 0x04; //定时器时钟1T模式
- T2L = 0xCD; //设置定时初值
- T2H = 0xD4; //设置定时初值
- AUXR |= 0x10; //定时器2开始计时
- IE2 = 0x04;
- P_SW2 =0x80; //D7位控制访问扩展SFR特殊寄存器 ,D4 D5位控制选用某端口做I2C的SCL SDA
- //I2C初始设置
- I2CCFG=0xE0; // I2C允许和速度控制寄存器
- I2CMSST=0x00;
- LCD1602CCH(); //LCD1602初始化
-
- EA = 1; //中断使能
-
- //主函数//********************
- while (1) //下面重复循环
- {
- SecJC(); //计数和BCD转换函数
- LCD1602SC(); //LCD1602全屏写入函数
- LCD_SC1(); //数据显示程序 1
- keycl(); //按键处理函数
-
- }
- }
- ////////////////***********************
- /*计数*/
- void SecJC() //定时执行操作(里面嵌套需要定期执行操作的函数,最短定期时间是1ms)
- {
- static unsigned int cnt = 0; // 1ms计数到1秒
- static unsigned long nsec = 9999; // 秒计数
- if(fabc1==1)
- {
- fabc1 =0; //清计数标志
- cnt++;
- if(cnt>=100)
- {
- cnt=0;
- nsec--; //段用于测试和显示正在计时
- LCD1602RAM1[1][3] = (nsec%10)+0x30; //个位
- LCD1602RAM1[1][2] = (nsec/10%10)+0x30; //十位
- LCD1602RAM1[1][1] = (nsec/100%10)+0x30; //百位
- LCD1602RAM1[1][0] = (nsec/1000%10)+0x30; //千位
- if(SWJC1==0) // ---只有设置键没按下时才读出时钟数
- {
- rx8025t_RX(); //RX8025T读出函数
- RX8025T_BCD(); //RX8025T时钟BCD数据转换成两字节
- }
- }
- nsec1++; //用于闪烁显示的计数
- if(nsec1>800)
- {
- nsec1=0;
- }
- }
- }
- //* 定时器0中断服务函数 */
- void InterruptTimer2() interrupt 12
- {
- fabc1=1; //设置计数标志为1
- keysm(); //按键扫描函数
-
- }
- //************************************以下是按键程序**************************************
- ///////////////////////////////////////////////////////
- //按键扫描函数 1行7个键 【按键扫描和处理函数参照书本《手把手教你学51单片机-C语言版》清华大学出版社, 第119页】
- void keysm()
- {
- unsigned char i;
- unsigned char push1; //暂时存放按键端口此前的值
-
- static unsigned char xdata keybuf[7] = { //1行7个键 7个缓冲字节
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff};
-
- SWEN=0;
- push1=P3; //暂时保存P3口原来的值 ,这里用P3口作按键扫描输入
- P3=0xff;
-
-
- //将一行的8个键值移入缓冲区
- keybuf[0]=(keybuf[0]<<1)|sw1;
- keybuf[1]=(keybuf[1]<<1)|sw2;
- keybuf[2]=(keybuf[2]<<1)|sw3;
- keybuf[3]=(keybuf[3]<<1)|sw4;
- keybuf[4]=(keybuf[4]<<1)|sw5;
- keybuf[5]=(keybuf[5]<<1)|sw6;
- keybuf[6]=(keybuf[6]<<1)|sw7;
- //消抖和更新键值
- for(i=0; i<7;i++) //每行7个键
- {
- if((keybuf[i] & 0x0f) == 0x00) //移入的键值 与 0x0f,如果是4次都是0(按下),那就是0x00输出
- { //如果4次都是1,那就是没按下或弹上。
- kkeysta[i] = 0;
- //如果其他值,那就是有抖动
- }
- else if((keybuf[i] & 0x0f) == 0x0f)
- {
- kkeysta[i] = 1;
- //每个键的实时情况反映在keysta[行]上,
- }
- }
- P3=push1; //恢复此前P3的值
- SWEN=1;
- }
- //---------------------------------------------------------------
- void keycl() //按键处理函数 【按键扫描和处理函数参照书本《手把手教你学51单片机-C语言版》清华大学出版社, 第119页】
- {
-
- static unsigned char xdata backup[7] = { //1行*7按键值备份的当前状态
- 1,1,1,1,1,1,1}; //加入static是静态局部变量,上电后只执行一次
-
- //////////sw1 处理程序
- if(backup[0] != kkeysta[0]) //如果本次按钮值与上一次不同,那执行下一句,否则就跳过到下一组
- {
- if(backup[0] == 0) //如果按键值是0,那就是有按下,那执行一下句操作,
- {
- SWJC1--; //按键减计数,显示闪烁位置右移*************
- if(SWJC1<0)
- {SWJC1=6;}
-
-
- }
- backup[0] = kkeysta[0]; //更新备份
- }
-
- //////////sw2 处理程序
- if(backup[1] != kkeysta[1])
- {
- if(backup[1] == 0)
- {
- SWJC1++; //按键加计数,显示闪烁位置左移*************
- if(SWJC1>=7)
- {SWJC1=0;}
-
- }
- backup[1] = kkeysta[1]; //更新备份
- }
- //////////sw3 处理程序
- if(backup[2] != kkeysta[2])
- {
- if(backup[2] == 0)
- {
- //LED_P31 = ~LED_P31; //测试语句 //***这条就是SW3对应执行的内容
- SWABC1(); //时间数值调整函数
- }
- backup[2] = kkeysta[2]; //更新备份
- }
-
- //////////sw4 处理程序
- if(backup[3] != kkeysta[3])
- {
- if(backup[3] == 0)
- {
- //LED_P31 = ~LED_P31; //测试语句 //***这条就是SW3对应执行的内容
- SET_RTC(); //设置好的数据保存到RX8025T
- }
- backup[3] = kkeysta[3]; //更新备份
- }
- //////////sw5 处理程序
- if(backup[4] != kkeysta[4])
- {
- if(backup[4] == 0)
- {
- LED_P31 = ~LED_P31; //测试语句 //***这条就是SW4对应执行的内容
-
- }
- backup[4] = kkeysta[4]; //更新备份
- }
- //////////sw6 处理程序
- if(backup[5] != kkeysta[5])
- {
- if(backup[5] == 0)
- {
- LED_P31 = ~LED_P31; //LED灯取反 测试语句
- SWJC1=0; // SWJC1计数置0,退设置操作
- }
- backup[5] = kkeysta[5]; //更新备份
- }
- //////////sw7 处理程序
- if(backup[6] != kkeysta[6])
- {
- if(backup[6] == 0)
- {
-
- I2C_1_CLR(); // 缓存数据清除
- }
- backup[6] = kkeysta[6]; //更新备份
- }
-
- //sw7 长按处理程序
- if(kkeysta[6]==0)
- {
- SW7_S1=1; //如果sw7按下那就置位标志作计时用
-
- }
- if(kkeysta[6]==1)
- {
- SW7_S1=0; //如果SW7弹开,那标志关闭
- SW7_S2=0; //清除计时
- //BUZ=1; //测试语句
- //LED_P31 =1; //熄灭LED 测试语句
- }
- }
- //---------------------------------------------------------
- //************************************以上是按键程序********************
-
-
- void Delay60us() //@11.0592MHz 60us延时 源自stc-isp软件生成
- {
- unsigned char i, j;
- _nop_();
- i = 1;
- j = 162;
- do
- {
- while (--j);
- } while (--i);
- }
- void delay_ms(unsigned int ms) //延时函数,ms,要延时的ms数, 这里只支持1~255ms. 自动适应主时钟.
- { // 延时函数 源自 STC官网例程
- unsigned int i;
- do{
- i = MAIN_Fosc / 13000;
- while(--i) ; //14T per loop
- }while(--ms);
- }
- //LCD1602指令写入 *******下面所有LCD1602操作的程序都是梁百万 参照网上前辈的程序重新编写
- void LCD1602ZL()
- {
- LCD_RS=0;
- LCD_EN=1;
- LCD_D0=LCD1602RAM2_D0;
- LCD_D1=LCD1602RAM2_D1;
- LCD_D2=LCD1602RAM2_D2;
- LCD_D3=LCD1602RAM2_D3;
- LCD_D4=LCD1602RAM2_D4;
- LCD_D5=LCD1602RAM2_D5;
- LCD_D6=LCD1602RAM2_D6;
- LCD_D7=LCD1602RAM2_D7;
- LCD_EN=0; //E,下降沿,让LCD读取
- Delay60us(); //延时80us
- }
- //LCD1602数据写入
- void LCD1602SZ()
- {
- LCD_RS=1;
- LCD_EN=1;
- LCD_D0=LCD1602RAM2_D0;
- LCD_D1=LCD1602RAM2_D1;
- LCD_D2=LCD1602RAM2_D2;
- LCD_D3=LCD1602RAM2_D3;
- LCD_D4=LCD1602RAM2_D4;
- LCD_D5=LCD1602RAM2_D5;
- LCD_D6=LCD1602RAM2_D6;
- LCD_D7=LCD1602RAM2_D7;
- LCD_EN=0; //E,下降沿,让LCD读取
- Delay60us(); //延时80us
- }
- //LCD1602初始化
- void LCD1602CCH()
- {
-
- LCD1602RAM2=0;
- delay_ms(15); //延时15毫秒
- LCD1602RAM2=0x38; //;16行*2,5*8
- LCD1602ZL(); //写入指令
- delay_ms(5); //延时5毫秒
- LCD1602RAM2=0x38; //;16行*2,5*8
- LCD1602ZL(); //写入指令
- delay_ms(5); //延时5毫秒
- LCD1602RAM2=0x08; // 关显示
- LCD1602ZL(); //写入指令
- delay_ms(1); //延时1毫秒
- LCD1602RAM2=0x01; //清屏
- LCD1602ZL(); //写入指令
- delay_ms(5); //延时5毫秒
- LCD1602RAM2=0x06; //;地址计数器AC自动加1,光标右移 *******
- delay_ms(1); //延时1毫秒
- LCD1602RAM2=0x0C; //开显示
- LCD1602ZL(); //写入指令
- delay_ms(1); //延时1毫秒
-
- }
- //------------------------------------------------------------------------
-
- void LCD_SC1() //全屏显示数据写入程序 把RX8025T分离出来后的BCD数据送到显示缓存,
- { //跟着在显示程序void LCD1602SC()那写入到显示屏
- LCD1602RAM1[0][0] ='2'; //年的2
- LCD1602RAM1[0][1] ='0'; //年的0
- LCD1602RAM1[0][2] =YEAR10 + 0x30; //年十位
- LCD1602RAM1[0][3] =YEAR1 + 0x30; //年个位
-
- LCD1602RAM1[0][4] = '/'; //分隔符
- LCD1602RAM1[0][5] =MONTH10 + 0x30; //月十位
- LCD1602RAM1[0][6] =MONTH1 + 0x30; //月个位
- LCD1602RAM1[0][7] ='/'; //分隔符
- LCD1602RAM1[0][8] =DAY10 + 0x30; //日十位
- LCD1602RAM1[0][9] =DAY1 + 0x30; //日个位
- LCD1602RAM1[0][10] ='/'; //分隔符
- LCD1602RAM1[0][11] =HOUR10 + 0x30; //时十位
- LCD1602RAM1[0][12] =HOUR1 + 0x30; //时个位
- LCD1602RAM1[0][13] =':'; //分隔符
- LCD1602RAM1[0][14] =MIN10 + 0x30; //分十位
- LCD1602RAM1[0][15] =MIN1+0x30; //分个位
- //LCD1602RAM1[1][0] =1+0X30;
- //LCD1602RAM1[1][1] =1+0X30;
- // LCD1602RAM1[1][2] = 1+0X30;
- //LCD1602RAM1[1][3] = 1+0X30;
-
- LCD1602RAM1[1][4] = 0X20;
- LCD1602RAM1[1][5] =0X20;
- LCD1602RAM1[1][6] =0X20;
- LCD1602RAM1[1][7] = 0X20;
- LCD1602RAM1[1][8] = 0X20;
- LCD1602RAM1[1][9] = 0X20;
- LCD1602RAM1[1][10] = 0X20;
- LCD1602RAM1[1][11] = 0X20;
- LCD1602RAM1[1][12] =0X20;
- LCD1602RAM1[1][13] =0X20;
- LCD1602RAM1[1][14] =SEC10+0X30; //秒十位
-
- LCD1602RAM1[1][15] =SEC1+0X30; //秒个位
- SCXL(); //LCD闪烁显示操作 // 调用大于0.6秒就对应键计数给对应缓存填上0X20
- }
- void I2C_1_CLR() //缓存数据清除
- {
- unsigned char i=8;
- while(i--)
- { I2C_1[i]=0x00; }
- }
- //---------------------------------------------------------------
- // LCD1602全屏显示程序,16字*2行
- void LCD1602SC()
- {
- unsigned char i=16; //每行的个数计数
- unsigned char x=0; //行数
- unsigned char y=0; //列数
-
- LCD1602RAM2=0x80; //这个是LCD第1行的地址
- LCD1602ZL(); //以地址/指令形式发送到LCD1602
- while(i--)
- {
- LCD1602RAM2=LCD1602RAM1[0][y];
- LCD1602SZ(); //以数据形式发送到LCD1602
- y++;
- };
- LCD1602RAM2=0xC0; //这个是LCD第2行的地址
- LCD1602ZL(); //以地址/指令形式发送到LCD1602
- i=16 ; //每行的个数计数
- y=0; //每行的个数
- while(i--)
- {
- LCD1602RAM2=LCD1602RAM1[1][y];
- LCD1602SZ(); //以数据形式发送到LCD1602
- y++;
- };
- }
- //----------------------------------------------
- void SCXL() //LCD闪烁显示操作 用于设置时某位的显示闪烁
- {
- if(SWJC1>=1)
- {
- if(nsec1>600) //大于0.6秒就在对应位置空格 SWJC1中设置按键对应数
- {
- if(SWJC1==1)
- {
- LCD1602RAM1[0][15]=0x20;
- }
- if(SWJC1==2)
- {
- LCD1602RAM1[0][14]=0x20;
- }
-
- if(SWJC1==3)
- {
- LCD1602RAM1[0][12]=0x20;
- LCD1602RAM1[0][11]=0x20;
- }
- if(SWJC1==4)
- {
- LCD1602RAM1[0][9]=0x20;
- LCD1602RAM1[0][8]=0x20;
- }
- if(SWJC1==5)
- {
- LCD1602RAM1[0][6]=0x20;
- LCD1602RAM1[0][5]=0x20;
- }
- if(SWJC1==6)
- {
- LCD1602RAM1[0][3]=0x20;
- LCD1602RAM1[0][2]=0x20;
- }
- else;
- }
- }
- }
- //--------------------------------------------------------
- // 硬件I2C串口 程序 参照STC官方文档有关I2C硬件操作的程序,由梁百万重新编写
- //下面的I2C读写函数可以读写8位地址的器件,如24C01~24C16, DS1307,RX8025T
- //变量说明
- //unsigned char xdata I2C_ADDR1 ;从器件的硬件地址
- //unsigned char xdata I2C_ADDR2 ;从器件的数据地址首址
- //unsigned char xdata I2C_X; 数据每次存放或取出的字节数,1到256字节
- //unsigned char xdata I2C_i; //主器件缓存的数据地址首址 (1维数组的个数计数变量)
- //unsigned char xdata I2C_1[16] // 主器件缓存 ,用变量I2C_i作位置计数
-
- //I2C多字节写入,1到16字节
- void I2C_TX() //I2C多字节写入,1到16字节
- {
- I2C_i=0; //主器件缓存的数据地址首址
- //第1步,起始+发送硬件地址+接收ACK
- I2CTXD=I2C_ADDR1; //从器件的硬件地址
- I2CMSCR=0x09; //此命令是 START+SDATA+ACK
-
- while (!(I2CMSST & 0x40)); //检查是否发送完成
- I2CMSST &= ~0x40;
- //第2步,发送从器件的数据地址首址+接收ACK
- I2CTXD=I2C_ADDR2; //从器件的数据地址首址
- I2CMSCR=0x0a; //此命令是SDATA+ACK
-
- while (!(I2CMSST & 0x40)); //检查是否发送完成
- I2CMSST &= ~0x40;
- while(I2C_X--) //第3步,主器件的缓存上写入多个数据到从器件
- {
- I2CTXD=I2C_1[I2C_i];//主器件缓存的数据地址首址
- I2CMSCR=0x0a; //此命令是SDATA+ACK
-
- while (!(I2CMSST & 0x40)); //检查是否发送完成
- I2CMSST &= ~0x40;
- I2C_i++; //主器件缓存的数据地址加1
- }
- //第4步,发送停止信号命令
- I2CMSCR=0x06; //停止信号命令
-
- while (!(I2CMSST & 0x40)); //检查是否发送完成
- I2CMSST &= ~0x40;
- I2CMSST &= ~0x40;
- }
- //--------------------------------------------------
- //I2C多字节读出,1到16字节
- void I2C_RX() //I2C多字节读出,1到16字节
- {
-
- I2C_i=0; //主器件缓存的数据地址首址
-
- //第1步,起始+发送硬件地址+接收ACK
- I2CTXD=I2C_ADDR1; //从器件的硬件地址
- I2CMSCR=0x09; //此命令是 START+SDATA+ACK
- while (!(I2CMSST & 0x40)); //检查是否发送完成
- I2CMSST &= ~0x40;
-
- //第2步,发送从器件的数据地址首址+接收ACK
- I2CTXD=I2C_ADDR2; //从器件的数据地址首址
- I2CMSCR=0x0a; //此命令是SDATA+ACK
-
- while (!(I2CMSST & 0x40)); //检查是否发送完成
- I2CMSST &= ~0x40;
- I2C_ADDR1++; //对硬件地址由写入改成读出, 地址数据D0位是1为读,0为写
- //第3步,再次发送,起始+发送硬件地址 读+接收ACK
- I2CTXD=I2C_ADDR1; //从器件的硬件地址
- I2CMSCR=0x09; //此命令是 START+SDATA+ACK
-
- while (!(I2CMSST & 0x40)); //检查是否发送完成
- I2CMSST &= ~0x40;
- while(I2C_X--) //第4步,读出多个数据并存放到缓存上
- {
- I2CMSCR=0x0b; //此命令是 接收数据+发送ACK
- while (!(I2CMSST & 0x40)); //检查是否发送完成
- I2CMSST &= ~0x40;
- I2C_1[I2C_i]=I2CRXD ; //读出后要传送到需要的寄存器
- I2C_i++; //主器件缓存的数据地址加1
- }
- //第5步,发出非应答信号NACK,
- I2CMSCR=0x0c; //此命令是 接收数据+发送NACK
-
- while (!(I2CMSST & 0x40)); //检查是否发送完成
- I2CMSST &= ~0x40;
- //第6步,停止
- I2CMSCR=0x06; //停止信号命令
- while (!(I2CMSST & 0x40)); //检查是否发送完成
- I2CMSST &= ~0x40;
- }
- //--------------------------------------------------------
- void rx8025t_RX() //RX8025T读出函数
- {
- I2C_ADDR1=0x64; // RX8025T硬件地址0x64, 24C04地址0ACH
- I2C_ADDR2=0x00; //从器件需要读出的地址首址
- I2C_X=8; //需要读出的字节数
- I2C_i=0x00; //缓存首址
- I2C_RX(); //读出数据
- }
- void rx8025t_TX() //RX8025T写入函数
- {
- I2C_ADDR1=0x64; // RX8025T硬件地址0x64, 24C04地址0ACH
- I2C_ADDR2=0x00; //从器件需要写入的地址首址
- I2C_X=8; //需要写入的字节数
- I2C_i=0x00; //缓存首址
- I2C_TX(); //写入数据
- }
- void RX8025T_BCD() //BCD数据转换成两字节
- {
- SEC1=(I2C_1[0]) & 0x0f; //取秒个位值
- SEC10=(I2C_1[0] & 0xf0)/16; //取秒十位值
- MIN1=(I2C_1[1]) & 0x0f; //取分个位值
- MIN10=(I2C_1[1] & 0xf0)/16; //取分十位值
- HOUR1=(I2C_1[2]) & 0x0f; //取时个位值
- HOUR10=(I2C_1[2] & 0xf0)/16;//取时十位值
- DAY1=(I2C_1[4]) & 0x0f; //取日个位值
- DAY10=(I2C_1[4] & 0xf0)/16; //取日十位值
- MONTH1=(I2C_1[5])& 0x0f; //取月个位值
- MONTH10=(I2C_1[5]& 0xf0)/16; //取月十位值
- YEAR1=(I2C_1[6])& 0x0f; //取年个位值
- YEAR10=(I2C_1[6]& 0xf0)/16; //取年个位值
- }
- //---------------------------------
- //SWJC1 ,不为0时是设置键有按下,才能作加数操作
- void SWABC1() //时间数值调整函数
- {
- if(SWJC1 != 0) //SWJC1 ,不为0,也就是左右移位有按下时才能加数操作
- {
- if(SWJC1 == 1) //分个位调整
- {
- MIN1++; //分个位加1
- if(MIN1>=10)
- {
- MIN1=0;
- }
- }
- if(SWJC1 == 2) //分十位调整
- {
- MIN10++;
- if(MIN10>=6)
- {
- MIN10=0;
- }
- }
- if(SWJC1 == 3) //小时位调整
- {
- HOUR1++;
- if(HOUR1>=10)
- {
- HOUR10++;
- HOUR1=0;
- }
- if(((HOUR10*10) + HOUR1) >= 24) //计算个位和十位总数是否大于24小时
- {
- HOUR10=0;
- HOUR1=0;
- }
- }
- //---------------------------------------------------------------//
- if(SWJC1 == 4) //日数调整
- {
- DAY1++;
- if(DAY1>=10)
- {
- DAY10++;
- DAY1=0;
- }
- //--------------------日数设置对应月数最大值的计算
- switch((MONTH10*10)+MONTH1)
- {
- case 1:if(((DAY10*10)+DAY1)>=32) {DAY10=0;DAY1=1;} break;
- case 3:if(((DAY10*10)+DAY1)>=32) {DAY10=0;DAY1=1;} break;
- case 5:if(((DAY10*10)+DAY1)>=32) {DAY10=0;DAY1=1;} break;
- case 7:if(((DAY10*10)+DAY1)>=32) {DAY10=0;DAY1=1;} break;
- case 8:if(((DAY10*10)+DAY1)>=32) {DAY10=0;DAY1=1;} break;
- case 10:if(((DAY10*10)+DAY1)>=32) {DAY10=0;DAY1=1;} break;
- case 12:if(((DAY10*10)+DAY1)>=32) {DAY10=0;DAY1=1;} break;
- case 4:if(((DAY10*10)+DAY1)>=31) {DAY10=0;DAY1=1;} break;
- case 6:if(((DAY10*10)+DAY1)>=31) {DAY10=0;DAY1=1;} break;
- case 9:if(((DAY10*10)+DAY1)>=31) {DAY10=0;DAY1=1;} break;
- case 11:if(((DAY10*10)+DAY1)>=31) {DAY10=0;DAY1=1;} break;
- case 2: if(((YEAR10*10)+YEAR1)%4 ==0)
- {
- if(((DAY10*10)+DAY1) >= 30) //闰年,那2月有29天
- {
- DAY10=0;DAY1=1;
- }
- }
- if(((YEAR10*10)+YEAR1)%4 !=0)
- {
- if(((DAY10*10)+DAY1) >= 29) //非闰年,那2月有28天
- {
- DAY10=0;DAY1=1;
- }
- }
- break;
-
- default:break;
- }
- //-------------------------------
- }
- //--------------------------------------------------------------
- if(SWJC1 == 5) //月数调整
- {
- MONTH1++;
- if(MONTH1>=10)
- {
- MONTH10++;
- MONTH1=0;
- }
- if(((MONTH10*10)+MONTH1) >= 13)
- {
- MONTH10=0;
- MONTH1=1;
- }
- switch((MONTH10*10)+MONTH1)
- {
- case 4:if(((DAY10*10)+DAY1)>=31) {DAY10=3;DAY1=0;} break; // 如果月数调整到是4.6.9.11,那要回头计算日数是否大于30
- case 6:if(((DAY10*10)+DAY1)>=31) {DAY10=3;DAY1=0;} break;
- case 9:if(((DAY10*10)+DAY1)>=31) {DAY10=3;DAY1=0;} break;
- case 11:if(((DAY10*10)+DAY1)>=31) {DAY10=3;DAY1=0;} break;
- case 2: if(((YEAR10*10)+YEAR1)%4 ==0)
- {
- if(((DAY10*10)+DAY1) >= 30) //闰年,那2月有29天 //如果月数调整到是2月,那要回头计算日数是否大于28/29
- {
- DAY10=2;DAY1=9;
- }
- }
- if(((YEAR10*10)+YEAR1)%4 !=0)
- {
- if(((DAY10*10)+DAY1) >= 29) //非闰年,那2月有28天
- {
- DAY10=2;DAY1=8;
- }
- }
- break;
-
- default:break;
- }
- }
- //----------------
- if(SWJC1 == 6) //年数调整
- {
- YEAR1++;
- if(YEAR1>=10)
- {
- YEAR10++;
- YEAR1=0;
- if(YEAR10>=10)
- {
- YEAR10=0;
- }
- }
- if(((YEAR10*10)+YEAR1)%4 !=0) //如设置是非闰年,那要回头看看和处理2月份的日数是否大于28
- { //
- if(((DAY10*10)+DAY1) >= 29) //非闰年,那2月有28天
- {
- DAY10=2;DAY1=8;
- }
- }
- }
- //-----------------------------------------
- }
- }
-
- void SET_RTC() //设置好的数据保存到RX8025T
- {
- if(SWJC1 != 0) //需要在只有按下过数值设置时才把数值存回到RX8025T
- {
- I2C_1[1] = ((MIN10*16) + MIN1); //把两个BCD数合并成一个字节
- I2C_1[2] = ((HOUR10*16) + HOUR1);
- I2C_1[4] = ((DAY10*16) + DAY1);
- I2C_1[5] = ((MONTH10*16) + MONTH1);
- I2C_1[6] = ((YEAR10*16) + YEAR1);
- I2C_1[0] =0;
- rx8025t_TX(); //RX8025T写入函数
- SWJC1=0; //存放好数据后就退出设置
- }
- else;
- }
复制代码
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
打赏
-
查看全部打赏
|