STM32使用HAL库驱动SD2405时钟芯片(模拟IIC)

STM32使用HAL库驱动SD2405时钟芯片(模拟IIC)


头文件

#ifndef SD2405_H__
#define SD2405_H__

#include "main.h"
#include "delay.h"


#define IIC_SCL PBout(13)
#define IIC_SDA PBout(14)
#define READ_SDA PBin(14)

/// SD2405寄存器地址定义 ///
#define SD2405_ADDR_YEAR   6
#define SD2405_ADDR_MONTH  5
#define SD2405_ADDR_DAY    4
#define SD2405_ADDR_WEEK   3
#define SD2405_ADDR_HOUR   2
#define SD2405_ADDR_MINUTE 1
#define SD2405_ADDR_SECOND 0

#define SD2405_ADDR_CTR1 0X0F
#define SD2405_ADDR_CTR2 0X10
#define SD2405_ADDR_CTR3 0X11


#define UChar2BCD(chr)  ((((chr) / 10) << 4) | ((chr) % 10))
#define BCD2UChar(bcd) ((((bcd) >> 4) * 10) + ((bcd) & 0X0F))


#pragma pack(1)
typedef struct
{
	uint16_t year;
	uint8_t month;
	uint8_t day;
	uint8_t hour;
	uint8_t minute;
	uint8_t second;
	uint8_t week;
}SD2405_DateTypedef;
#pragma pack()

void SD2405_Init(void);
void SD2405_Write_Time(SD2405_DateTypedef* date);
SD2405_DateTypedef* SD2405_Read_Time(void);

#endif

源文件

#include "sd2405.h"
#include 

void IIC_Init(void)
{
/* 此处添加你的IIC引脚初始化IO的代码,我是直接使用STM32CubeMX生成的 */
	IIC_SCL = 1;
	IIC_SDA = 1;
}

/// 设置IIC的SDA引脚为输出
void SDA_SET_OUT(void)
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};
	GPIO_InitStruct.Pin = IIC_SCL_Pin | IIC_SDA_Pin;
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
	HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}

/// 设置IIC的SDA引脚为输入
void SDA_SET_IN(void)
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};
	GPIO_InitStruct.Pin = IIC_SDA_Pin;
	GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}

void IIC_Start(void)
{
	SDA_SET_OUT();
	IIC_SDA = 1;
	IIC_SCL = 1;
	delay_us(5);
	IIC_SDA = 0; //START:when CLK is high,DATA change form high to low
	delay_us(6);
	IIC_SCL = 0;
}

void IIC_Stop(void)
{
	SDA_SET_OUT();
	IIC_SCL = 0;
	IIC_SDA = 0; //STOP:when CLK is high DATA change form low to high
	IIC_SCL = 1;
	delay_us(6);
	IIC_SDA = 1;
	delay_us(6);
}

uint8_t IIC_Wait_Ack(void)
{
	uint8_t tempTime = 0;
	IIC_SDA = 1;
	delay_us(1);
	SDA_SET_IN();
	IIC_SCL = 1;
	delay_us(1);
	while (READ_SDA)
	{
		tempTime++;
		if (tempTime > 250)
		{
			IIC_Stop();
			return 1;
		}
	}
	IIC_SCL = 0;
	return 0;
}

void IIC_Ack(void)
{
	IIC_SCL = 0;
	SDA_SET_OUT();
	IIC_SDA = 0;
	delay_us(2);
	IIC_SCL = 1;
	delay_us(5);
	IIC_SCL = 0;
}

void IIC_NAck(void)
{
	IIC_SCL = 0;
	SDA_SET_OUT();
	IIC_SDA = 1;
	delay_us(2);
	IIC_SCL = 1;
	delay_us(5);
	IIC_SCL = 0;
}

void IIC_Send_Byte(uint8_t txd)
{
	uint8_t t;
	SDA_SET_OUT();
	IIC_SCL = 0;
	for (t = 0; t < 8; t++)
	{
		if ((txd & 0x80) > 0) //0x80  1000 0000
			IIC_SDA = 1;
		else
			IIC_SDA = 0;
		txd <<= 1;
		delay_us(2);
		IIC_SCL = 1;
		delay_us(2);
		IIC_SCL = 0;
		delay_us(2);
	}
}

uint8_t IIC_Read_Byte(uint8_t ack)
{
	uint8_t i, receive = 0;
	SDA_SET_IN();
	for (i = 0; i < 8; i++ )
	{
		IIC_SCL = 0;
		delay_us(2);
		IIC_SCL = 1;
		receive <<= 1;
		if (READ_SDA)receive++;
		delay_us(1);
	}
	if (!ack)
		IIC_NAck();
	else
		IIC_Ack();
	return receive;
}

void SD2405_Init(void)
{
	IIC_Init();
}

void SD2405_WriteOneByte(uint8_t WriteAddr, uint8_t Data)
{
	IIC_Start();
	IIC_Send_Byte(0x64);
	IIC_Wait_Ack();
	IIC_Send_Byte(WriteAddr);
	IIC_Wait_Ack();
	IIC_Send_Byte(Data);
	IIC_Wait_Ack();
	IIC_Stop();
	delay_ms(10);
}

uint8_t SD2405_ReadOneByte(uint8_t ReadAddr)
{
	uint8_t temp;
	IIC_Start();
	IIC_Send_Byte(0x64);
	IIC_Wait_Ack();
	IIC_Send_Byte(ReadAddr);
	IIC_Wait_Ack();
	IIC_Start();
	IIC_Send_Byte(0x65);
	IIC_Wait_Ack();
	temp = IIC_Read_Byte(0);
	IIC_Stop();
	return temp;
}

/// 使能写
void Write_On(void)
{
	SD2405_WriteOneByte(SD2405_ADDR_CTR1, 0x84);
	SD2405_WriteOneByte(SD2405_ADDR_CTR2, 0x80);
}

/// 禁止写
void Write_Off(void)
{
	SD2405_WriteOneByte(SD2405_ADDR_CTR1, 0x00);
	SD2405_WriteOneByte(SD2405_ADDR_CTR2, 0x52);
}

/// 写入时间
void SD2405_Write_Time(SD2405_DateTypedef* date)
{
	Write_On();
	SD2405_WriteOneByte(SD2405_ADDR_YEAR,   UChar2BCD(date->year - 2000));
	SD2405_WriteOneByte(SD2405_ADDR_MONTH,  UChar2BCD(date->month));
	SD2405_WriteOneByte(SD2405_ADDR_DAY,    UChar2BCD(date->day));
	SD2405_WriteOneByte(SD2405_ADDR_HOUR,   UChar2BCD(date->hour) | 0X80);  /* 24小时制 */
	SD2405_WriteOneByte(SD2405_ADDR_MINUTE, UChar2BCD(date->minute));
	SD2405_WriteOneByte(SD2405_ADDR_SECOND, UChar2BCD(date->second));
	SD2405_WriteOneByte(SD2405_ADDR_WEEK,   UChar2BCD(date->week));
	Write_Off();
}

/// 读取时间
SD2405_DateTypedef* SD2405_Read_Time(void)
{
	static SD2405_DateTypedef time;
	memset(&time, 0X00, sizeof(SD2405_DateTypedef));
	time.year   = SD2405_ReadOneByte(SD2405_ADDR_YEAR);
	time.month  = SD2405_ReadOneByte(SD2405_ADDR_MONTH);
	time.day    = SD2405_ReadOneByte(SD2405_ADDR_DAY);
	time.hour   = SD2405_ReadOneByte(SD2405_ADDR_HOUR);
	time.minute = SD2405_ReadOneByte(SD2405_ADDR_MINUTE);
	time.second = SD2405_ReadOneByte(SD2405_ADDR_SECOND);
	time.week   = SD2405_ReadOneByte(SD2405_ADDR_WEEK);
	time.year   = BCD2UChar(time.year) + 2000;
	time.month  = BCD2UChar(time.month);
	time.day    = BCD2UChar(time.day);
	time.hour   = BCD2UChar(time.hour & 0X7F);
	time.second = BCD2UChar(time.second);
	time.minute = BCD2UChar(time.minute);
	time.week   = BCD2UChar(time.week);
	return &time;
}












你可能感兴趣的:(STM32)