一、芯片引脚介绍
1.芯片引脚
2.引脚描述
二、系统结构图
三、功能描述
1.时钟功能
2.警报功能
3.高精度时间调整功能
4.晶振停振监测
5.周期中断
6.32kHz 时钟输出
四、寄存器的描述
五、程序代码
XJ8372.C
/*
* XJ8372.c
*
* Created on: 2024年8月8日
* Author: Administrator
*/
#include "softiic.h"
#include "XJ8372.h"
#include "usart.h"
#include <stdio.h>
//XJ8372的IIC读
uint8_t XJ8372ReadOneByte(uint8_t ReadAddr)
{
uint8_t temp=0;
bsp_analog_i2c_start();
bsp_analog_i2c_send_byte(0X64);
bsp_analog_i2c_wait_ack();
bsp_analog_i2c_send_byte(ReadAddr);
bsp_analog_i2c_wait_ack();
bsp_analog_i2c_start();
bsp_analog_i2c_send_byte(0X65);
bsp_analog_i2c_wait_ack();
temp= bsp_analog_i2c_read_byte();
bsp_analog_i2c_nack();
bsp_analog_i2c_stop();
return temp;
}
//XJ8372的IIC写
void XJ8372WriteOneByte(uint8_t WriteAddr,uint8_t DataToWrite)
{
bsp_analog_i2c_start();
bsp_analog_i2c_send_byte(0x64);
bsp_analog_i2c_wait_ack();
bsp_analog_i2c_send_byte(WriteAddr);
bsp_analog_i2c_wait_ack();
bsp_analog_i2c_send_byte(DataToWrite);
bsp_analog_i2c_wait_ack();
bsp_analog_i2c_stop();
}
//XJ8372的IIC连续写
void XJ8372sequence_write(uint8_t WriteAddr,uint8_t* data,int length)
{
bsp_analog_i2c_start();
bsp_analog_i2c_send_byte(0X64);
bsp_analog_i2c_wait_ack();
bsp_analog_i2c_send_byte(WriteAddr);
bsp_analog_i2c_wait_ack();
for (int i = 0; i < length; i++)
{
bsp_analog_i2c_send_byte(*(data+i));
bsp_analog_i2c_wait_ack();
}
bsp_analog_i2c_nack();
bsp_analog_i2c_stop();
}
//时间初始化结构体
Clock_Typedef Clock_init={
.SEC=0x50,
.MIN=0x59,
.HOUR=0x18,
.WEEK=0x01,
.DAY=0x01,
.MONTH=0x01,
.YEAR=0x24
};
/***
功能:设定XJ8372的时间
输入:Clock_init的地址
返回:无
*****/
void SET_XJ8372TIMER(Clock_Typedef* clock)
{
XJ8372WriteOneByte(RS5C_REG_CTRL2,1<<5);//设置24小时
XJ8372sequence_write(XJ8372_REG_SECS,(uint8_t*)clock ,7);
}
/***
功能:打印出XJ8372的时间
输入:无
返回:无
*****/
void printf_XJ8372TIMER(void)
{
printf("北京时间 ");
printf(" 20%x年 ",XJ8372ReadOneByte(XJ8372_REG_YEAR)& 0x7f);
printf("%x月 ",XJ8372ReadOneByte(XJ8372_REG_MONTH));
printf("%x日 ",XJ8372ReadOneByte(XJ8372_REG_DAY)& 0x7f);
//printf(" 星期 %x ",XJ8372ReadOneByte(XJ8372_REG_WDAY)& 0x7f);
switch(XJ8372ReadOneByte(XJ8372_REG_WDAY)& 0x7f)
{
case 1:printf(" 星期 一");break;
case 2:printf(" 星期 二");break;
case 3:printf(" 星期 三");break;
case 4:printf(" 星期 四");break;
case 5:printf(" 星期 五");break;
case 6:printf(" 星期 六");break;
case 7:printf(" 星期 日");break;
default:printf("error");
}
printf(" %x:",XJ8372ReadOneByte(XJ8372_REG_HOURS)& 0x3f);
printf(" %x:",XJ8372ReadOneByte(XJ8372_REG_MINS)& 0x7f);
printf(" %x \r\n",XJ8372ReadOneByte(XJ8372_REG_SECS)& 0x7f);
HAL_Delay(1000);
}
/***
功能:校准时间
输入:可以通过输入不同参数,来调节精度
返回:无
*****/
void Time_aligned(uint8_t aligne)
{
XJ8372WriteOneByte(RS5C372_REG_TRIM,aligne);
}
//设置闹钟A赋初值
Alarm_A_Typedef Alarm_A_init={
.MIN_Alarm_A=0x00,
.HOUR_Alarm_A=0x19,
.WD_Alarm_A=0x7f,
};
void Alarm_A_Init(Alarm_A_Typedef*alarm)
{
XJ8372sequence_write(RS5C_REG_ALARM_A_MIN,(uint8_t*)alarm ,3);
XJ8372WriteOneByte(RS5C_REG_CTRL1,1<<7);
}
//设置闹钟B赋初值
Alarm_B_Typedef Alarm_B_init={
.MIN_Alarm_B=0x00,
.HOUR_Alarm_B=0x19,
.WD_Alarm_B=0x7f,
};
void Alarm_B_Init(Alarm_B_Typedef*alarm)
{
XJ8372sequence_write(RS5C_REG_ALARM_B_MIN,(uint8_t*)alarm ,3);
XJ8372WriteOneByte(RS5C_REG_CTRL1,1<<6);
}
/***
功能:获取闹钟A的状态
输入:
返回: 1 闹钟匹配上了
0 闹钟没匹配上
*****/
uint8_t Alarm_A_flag (void)
{
uint8_t Control2_data;
uint8_t alarm_A_flag;
Control2_data=XJ8372ReadOneByte(RS5C_REG_CTRL2);
Control2_data=Control2_data&0x02;
alarm_A_flag=Control2_data>>1;
return alarm_A_flag;
}
/***
功能:设置输出引脚为A或者B,设置输出频率为1HZ或者2HZ
输入:
INTx : INTA引脚 INTB引脚
fre : Pulse_Mode2Hz Pulse_Mode1Hz
返回:无
*****/
void Set_Pulse_Mode(uint8_t fre,uint8_t INTx)
{
uint8_t Control1_data;
uint8_t Control2_data;
Control1_data=XJ8372ReadOneByte(RS5C_REG_CTRL1);
Control1_data=Control1_data&0xF8;
Control2_data=XJ8372ReadOneByte(RS5C_REG_CTRL2);
Control2_data=Control2_data|0X08;
if(INTx==INTA)
{
XJ8372WriteOneByte(RS5C_REG_CTRL1,(Control1_data|fre)&0XCF);//设置频率和输出额引脚为A
}
else
{
XJ8372WriteOneByte(RS5C_REG_CTRL2,Control2_data);
XJ8372WriteOneByte(RS5C_REG_CTRL1,(Control1_data|fre)|0X20);//设置频率和输出额引脚为B
}
}
/***
功能:设置输出引脚为A或者B,设置每秒、每分钟,每小时、每个月
输入:
INTx : INTA引脚
INTB引脚
tim : Every_second
Every_minute,
Every_hour,
Every_month,
返回:无
*****/
void Set_Level_Mode(uint8_t tim,uint8_t INTx)
{
uint8_t Control1_data;
uint8_t Control2_data;
Control1_data=XJ8372ReadOneByte(RS5C_REG_CTRL1);
Control1_data=Control1_data&0xF8;
Control2_data=XJ8372ReadOneByte(RS5C_REG_CTRL2);
Control2_data=Control2_data|0X08;
if(INTx==INTA)
{
XJ8372WriteOneByte(RS5C_REG_CTRL1,(Control1_data|tim)&0XCF);//设置频率和输出额引脚为A
}
else
{
XJ8372WriteOneByte(RS5C_REG_CTRL2,Control2_data);
XJ8372WriteOneByte(RS5C_REG_CTRL1,(Control1_data|tim)|0X20);//设置频率和输出额引脚为B
}
}
/***
功能:由于Level_Mode会导致引脚输出低电平,这个函数可以清除并且恢复高电平
输入:
返回:无
*****/
void clear_Level_Mode (void)
{
uint8_t Control2_data;
Control2_data=XJ8372ReadOneByte(RS5C_REG_CTRL2);
Control2_data=Control2_data&0XFB;
XJ8372WriteOneByte(RS5C_REG_CTRL2,Control2_data);
}
/***
功能:设置24小时制或者12小时制
输入:
返回:无
*****/
void Set_12or24Mode (void)
{
uint8_t Control2_data;
Control2_data=XJ8372ReadOneByte(RS5C_REG_CTRL2);
Control2_data=Control2_data|0X20;
XJ8372WriteOneByte(RS5C_REG_CTRL2,Control2_data);
}
/***
功能:控制INTB是否输出32KHZ
输入:
SET : 不输出
RESET : 输出
返回:无
*****/
void Output_32kHz (uint8_t CLEN)
{
uint8_t Control2_data;
Control2_data=XJ8372ReadOneByte(RS5C_REG_CTRL2);
if(CLEN==1)
{
Control2_data=Control2_data|0X08;
}
else
{
Control2_data=Control2_data&0XF7;
}
XJ8372WriteOneByte(RS5C_REG_CTRL2,Control2_data);
}
XJ8372.H
/*
* XJ7372.h
*
* Created on: 2024年8月8日
* Author: Administrator
*/
#ifndef __XJ8372_H_
#define __XJ8372_H_
//设置时间结构体
typedef struct{
uint8_t SEC;
uint8_t MIN;
uint8_t HOUR;
uint8_t WEEK;
uint8_t DAY;
uint8_t MONTH;
uint8_t YEAR;
}Clock_Typedef;
extern Clock_Typedef Clock_init;
//设置闹钟A的结构体
typedef struct{
uint8_t MIN_Alarm_A;
uint8_t HOUR_Alarm_A;
uint8_t WD_Alarm_A;
}Alarm_A_Typedef;
//设置闹钟B的结构体
typedef struct{
uint8_t MIN_Alarm_B;
uint8_t HOUR_Alarm_B;
uint8_t WD_Alarm_B;
}Alarm_B_Typedef;
extern Alarm_A_Typedef Alarm_A_init;
extern Alarm_B_Typedef Alarm_B_init;
enum XJ8372_Pulse_Mode
{
Pulse_Mode2Hz=0x02,
Pulse_Mode1Hz,
};
enum XJ8372_Level_Mode
{
Every_second =0x04,
Every_minute,
Every_hour,
Every_month,
};
#define XJ8372_REG_SECS 0X00
#define XJ8372_REG_MINS 0X10
#define XJ8372_REG_HOURS 0X20
#define XJ8372_REG_WDAY 0X30
#define XJ8372_REG_DAY 0X40
#define XJ8372_REG_MONTH 0X50
#define XJ8372_REG_YEAR 0X60
#define RS5C372_REG_TRIM 0X70
#define RS5C_REG_ALARM_A_MIN 0X80 /* or ALARM_W */
#define RS5C_REG_ALARM_A_HOURS 0X90
#define RS5C_REG_ALARM_A_WDAY 0XA0
#define RS5C_REG_ALARM_B_MIN 0XB0 /* or ALARM_W */
#define RS5C_REG_ALARM_B_HOURS 0XC0
#define RS5C_REG_ALARM_B_WDAY 0XD0
#define RS5C_REG_CTRL1 0XE0
#define RS5C_REG_CTRL2 0XF0
#define INTA 0
#define INTB 1
#define RESET 0
#define SET 1
void SET_XJ8372TIMER(Clock_Typedef* clock);
uint8_t XJ8372ReadOneByte(uint8_t ReadAddr);
void XJ8372WriteOneByte(uint8_t WriteAddr,uint8_t DataToWrite);
void printf_XJ8372TIMER(void);
void XJ8372sequence_write(uint8_t WriteAddr,uint8_t* data,int length);
void Alarm_A_Init(Alarm_A_Typedef*alarm);
void Set_Pulse_Mode(uint8_t fre,uint8_t INTx);
void Set_Level_Mode(uint8_t tim,uint8_t INTx);
void clear_Level_Mode (void);
void Set_12or24Mode (void);
void Output_32kHz (uint8_t CLEN);
uint8_t Alarm_A_flag (void);
void Alarm_B_Init(Alarm_B_Typedef*alarm);
#endif
main.c
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_TIM2_Init();
/* USER CODE BEGIN 2 */
bsp_analog_i2c_init();
HAL_TIM_Base_Start_IT(&htim2);
SET_XJ8372TIMER(&Clock_init);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
printf_XJ8372TIMER();
// printf_XJ8372TIMER();
}
/* USER CODE END 3 */
}