|

楼主 |
发表于 2023-3-1 11:52:39
|
显示全部楼层
本帖最后由 慕名而来 于 2023-3-1 12:12 编辑
开天斧板子使用RX8025T是没问题的,只要启用它的硬件I2C总线挂载8025就可以了,另外,还有一个简易方案,这个芯片也有自带的RTC实时时钟,也可以读年月日时分秒数据,只是受限与内部振荡器精度或者外接32K晶振的热稳定性而精度不易弄的太好,咱们可以利用8025做STC8的外部时钟源(做晶振用),此时8025不用连接通讯线路,只需要将8025的pin3-FOUT引脚连接到板上J2端子的pin3焊盘(P1.7)的XTALI时钟输入引脚上就可以了(此时STC8的P1.6脚空闲也不能用于其他控制了),开天斧板子设置RTC功能时设置为使用外部时钟即可,另外它的寄存器数据是HEX码,无需进行数据转换这是很人性化的设计,这个方案我曾经用STC8H8K64TL验证过,如果你利用这个方案的话可以先试试,如果编程有问题咱们再交流解决。
一、接线图如下:
二、下面是STC8H的RTC初始化函数供参考:
//----RTC初始化函数------------------------------------------------
//YEAR、MONTH、DAY、HOUR、MIN、SEC 这些变量名称已在头文件中定义了可以直接使用
//需要注意的是不同的STC8头文件中的变量拼写或有不同应以自己使用的头文件为准。
void RTC_config(void)
{
X32KCR = 0xc0; //启动外部 32K 晶振
while (!(X32KCR & 0x01)); //等待时钟稳定
RTCCFG &= ~0x02; //选择外部 32K时钟 作为 RTC 时钟源
RTCCFG |= 0x01; //触发 RTC 寄存器初始化
RTCIF = 0; //清中断标志
RTCIEN = 0x08; //使能 RTC 秒中断
RTCCR = 0x01; // RTC 使能
}
//----RTC秒中断函数---------------------------------------------------
void RTC_Isr() interrupt 36
{
if(RTCIF & 0x08) //判断是否秒中断
{
RTCIF &= ~0x08; //清除中断标志
B1S_Flag = 1;
}
}
//====分别读取时间数据============================
void read_RTCdata()
{
ye=YEAR;
mo=MONTH;
da=DAY;
hi=HOUR;
mi=MIN;
si=SEC;
}
//====写入STC8H单片机RTC寄存器数据函数==========================
void write_RTC(u8 *timedata)
{
INIYEAR = timedata[0];
INIMONTH = timedata[1];
INIDAY = timedata[2];
INIHOUR = timedata[3];
INIMIN = timedata[4];
INISEC = timedata[5];
INISSEC = timedata[6];
}
//====RTC数据更新函数=========================
//将调整后的时间数据写入RTC寄存器中
void RTC_Data_Update()
{
time[0]=ye;
time[1]=mo;
time[2]=da;
time[3]=hi;
time[4]=mi;
time[5]=0;
time[6]=0;
write_RTC(&time);
RTCCFG |= 0x01; //触发 RTC 寄存器初始化
}
三、下面是不使用STC8H内部RTC而是使用I2C通讯驱动8025的相关代码:
//------I2C.c-----------------
bit busy;
//------------------------------------------
void I2C_init()
{
I2C_USE_P15P14();//I2C端口引脚P1.5/P1.4
I2CCFG = 0xE0; //使能 I2C 主机模式
I2CMSST = 0x00;
}
//------------------------------------------
void Start()
{
busy = 1;
I2CMSCR = 0x81; //发送 START 命令
while (busy);
}
//------------------------------------------
void SendData(char dat)
{
I2CTXD = dat; //写数据到数据缓冲区
busy = 1;
I2CMSCR = 0x82; //发送 SEND 命令
while (busy);
}
//------------------------------------------
void RecvACK()
{
busy = 1;
I2CMSCR = 0x83; //发送读 ACK 命令
while (busy);
}
//------------------------------------------
char RecvData()
{
busy = 1;
I2CMSCR = 0x84; //发送 RECV 命令
while (busy);
return I2CRXD;
}
//------------------------------------------
void SendACK()
{
I2CMSST = 0x00; //设置 ACK 信号
busy = 1;
I2CMSCR = 0x85; //发送 ACK 命令
while (busy);
}
//------------------------------------------
void SendNAK()
{
I2CMSST = 0x01; //设置 NAK 信号
busy = 1;
I2CMSCR = 0x85; //发送 ACK 命令
while (busy);
}
//------------------------------------------
void Stop()
{
busy = 1;
I2CMSCR = 0x86; //发送 STOP 命令
while (busy);
}
四、下面是RX8025T的底层驱动函数:
//----在指定寄存器中写入一个数据------------------
void write_8025(u8 addr,u8 date)//(地址,数据)
{
Start();
SendData(0x64);
RecvACK();
SendData(addr);
RecvACK();
SendData(date);
RecvACK();
Stop();
}
//----在指定寄存器中读出一个数据------------------
//专用于中断函数调用
u8 read_8025(u8 addr)
{
u8 date;
Start();
SendData(0x64);
RecvACK();
SendData(addr);
RecvACK();
Start();
SendData(0x65);
RecvACK();
date = RecvData();
SendNAK();
Stop();
return date;
}
//----BCD转10进制换算函数用于时钟输出--------
u8 BCD_D(u8 num)
{
u8 L;
L=(num/16)*10+(num%16);
return L;
}
//----10进制转BCD换算函数用于时钟设置--------
u8 D_BCD(u8 num)
{
u8 L;
L=(num/10)*16+(num%10);
return L;
}
//====打包读出RX8025实时时间数据========================================
//读取寄存器的数据为二--十进制编码(BCD)格式
//数据变换成十进制数据(数据编码为十六进制后台运行为二进制)
void read_8025time(u8 *timedata)
{
u8 i;
for(i=0; i<7; i++) //分 7 次读取 秒分时日月周年
{
timedata=BCD_D(read_8025(i);
}
}
//====打包写入RX8025初始化的调整后的时间数据==========================
//写入寄存器的数据为BCD格式数据
void write_8025time(u8 *timedata)
{
u8 i;
for (i=0; i<7; i++) //7 次写入 秒分时日月周年
{
write_8025(i,D_BCD(timedata));
}
}
//====分别读取时间数据============================
void read_8025data()
{
read_8025time(&time);
ye=time[6];
mo=time[5];
da=time[4];
hi=time[2];
mi=time[1];
si=time[0];
}
//====RX_8025初始化函数==================================
void init_8025()
{
u8 VLF;
//~~~~以下为是否初始化时间的判断操作~~~~
VLF=((read_8025(0x0E))&0x02);//读标志寄存器E的VLF位,如果为1则提示实时时间数据丢失
if(VLF)
{
write_8025(0x0E,0x00); //清除所有标志
write_8025time(&time_init);//如因掉电而数据丢失则重新上电时显示20-1-1 8:30:00星期3
}
//~~~~以下为时间(秒)更新中断的设置~~~~
write_8025(0x0F,0x00); //设置UIE=0关闭更新中断
write_8025(0x0D,0x00); //设置USEL=0(设为秒更新)
write_8025(0x0F,0xE0); //设置UIE=1使能更新中断启动INT、关闭其他中断,设置间隔30S温补一次(CSEL0,1=10)
}
五、关于开天斧板子的使用有几个问题需要注意一下:
1.上手时先处理与外部设备的电源电压的匹配问题,板子默认为5V供电、5V输出,如果外部设备是3.3V时需要修改板上的相关电阻的位置,使板上标注VCC的引脚电压为3.3V。
2.用到板子的接口连接外部设备时,也需要根据原理图核对相关引脚是否连接了其他功能的电路,需要加焊、挪移、去除一些与引脚连接的电阻才可以正常使用。
3.上述这些在原理图上都有详细标注,用之前需要相信查看原理图。
六、关于STC8H头文件的一点使用心得的经验分享:
STC8H.h头文件是个挺奇葩的头文件,使用STC8单片机时建议仔细查看这个头文件,因为它包罗万象,比如引用了这个头文件就不用在程序中做下列宏定义了:
#define uchar unsigned char
#define uint unsigned int
#define u32 unsigned long
直接就用u8,u16,u32就可以了因为头文件里有宏定义了,如果是自己使用的话还可以自行丰富这个头文件,例如,STC8H单片机使用时必须首先设置I/O口,否则他是无法运行的,我就曾经弄了很久也没能点亮LED灯,于是我在头文件里就添加了如下代码:
#define GPIO_set() {P0M0 = 0x00; P0M1 = 0x00; P1M0 = 0x00; P1M1 = 0x00;P2M0 = 0x00; P2M1 = 0x00;P3M0 = 0x00; P3M1 = 0x00;P4M0 = 0x00; P4M1 = 0x00;P5M0 = 0x00; P5M1 = 0x00;P6M0 = 0x00; P6M1 = 0x00;P7M0 = 0x00; P7M1 = 0x00;}
此后建立工程后只要在主函数的主循环前加入一条:GPIO_set() ; 就可以少写一大堆的PxMx=0x00端口设置代码了,另外,这个单片机经常要用到sfrx寄存器P_SW2的开关设置,只要在主函数开头加上 EAXSFR();这句代码就可以在各个函数中无视P_SW2寄存器的设置了,比如使用内部RTC是,你可以直接使用 YEAR;MONTH;DAY;HOUR;MIN;SEC;这些变量字来调用RTC寄存器中的数据而不用另外定义变量了,因为头文件中已经定义好了(不同的头文件可能拼写有不同)。如上这些还有很多仔细查看这个头文件可以大大的方便编程。
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
|