本文使用的工程代码如下:
(1条消息) stm32iic驱动ds1307实际使用驱动,参考博客:资源-CSDN文库
上次我记得写了一个使用开发板测试DS1307的测试例程,DS1307也是使用测试板,后面项目上具体使用了,又优化了驱动代码,这里做个简单的说明
做了哪些优化呢?
00h 地址的第 7 位为器件时钟允许位(CH), 此位为 1 则芯片未开始工作, 即时钟未走时, 所以在上电时单片机要先读出秒, 并判断位 7(CH) 是否为1,如为 1 要把该位清零写入秒寄存器(地址为 0) ,并把其他的时间单元设定为默认值。 如果上电复位时读出的秒的最高位 CH 为 0,说明时钟已工作(前已对 CH清 0,且停电 后有备用电池), 此时不能重写时间单元!
按照上述论述,主要是针对开始上电,判断DS1307是否已经配置了时钟进行判断,如果配置了DS1307就不再重复配置,重复配置会导致时间丢失。这里使用如下函数
u8 ds1307GetCH(void)//CH 1标明芯片未开始工作,需要将该位清零
{
u8 add = 0x00, CH;
// unsigned char temp;
unsigned char dat;
ds1307_IIC_Start();
ds1307_IIC_Send_Byte(0xD0);
ds1307_IIC_Wait_Ack();
ds1307_IIC_Send_Byte( add);
ds1307_IIC_Wait_Ack();
ds1307_IIC_Stop();
ds1307_IIC_Start();
ds1307_IIC_Send_Byte(0xD1);
ds1307_IIC_Wait_Ack();
dat=ds1307_IIC_Read_Byte(add);
ds1307_IIC_NAck();
ds1307_IIC_Stop();
if(dat & 0x80)
{
CH = 1;
}
else
{
CH = 0;
}
return CH;
}
这里原理图设计如下,其中TIME_INT管脚这里没有使用,这个管脚主要是DS1307可以提供一些时钟,主要是iic管脚对应MCU的PA6/PA7
DS1307的简单介绍如下
DS1307串行实时时钟(RTC)是一款低功耗、二-十进制编码(BCD)的时钟/日历,外加56字节NV RAM。地址与数据通过I²C接口串行传输。时钟/日历提供秒、分、时、星期、日、月和年信息。对于少于31天的月份,将自动调整月末日期,包括闰年修正。时钟格式可以是24小时或带AM/PM指示的12小时格式。DS1307内置电源检测电路,检测主电源失效时自动切换到备用电源,以保持时间、日期信息和计时。
- RTC提供秒、分钟、小时、日、月、星期及年计时,带闰年补偿,有效期至2100年
- 56字节、电池备份、通用RAM,写次数不受限制
- I²C串口
- 可编程方波输出信号
- 自动电源失效检测和切换电路
- 电池备份模式下,振荡器运行功耗低于500nA
- -40°C至+85°C工作温度范围
- 可用于8引脚塑料DIP等
stm32cubemx配置如下
主要使用原理图中的PA6/PA7,配置为输出模式
主要使用外部时钟,倍频到72MHZ
软件主函数中针对DS1307的初始化配置如下
这里比较简单,就是配置或者读取DS1307的时间信息到内存
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();
/* USER CODE BEGIN 2 */
delay_init();
ds1307Init();
//更新实时时钟时间
ds1307UpdateTime();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
实际使用的DS1307的读写函数
unsigned char Write1307(unsigned char add,unsigned char dat)//写一字节到对应地址去
{
unsigned char temp;
//转BCD码再写入1307
temp=dat/10;
temp<<=4;
temp=dat%10+temp;
ds1307_IIC_Start();
ds1307_IIC_Send_Byte(0xD0);
ds1307_IIC_Wait_Ack();
ds1307_IIC_Send_Byte(add);
ds1307_IIC_Wait_Ack();
ds1307_IIC_Send_Byte(temp);
ds1307_IIC_Stop();
return (0);
}
unsigned char Read1307(unsigned char add)
{
unsigned char temp;
unsigned char dat;
ds1307_IIC_Start();
ds1307_IIC_Send_Byte(0xD0);
ds1307_IIC_Wait_Ack();
ds1307_IIC_Send_Byte( add);
ds1307_IIC_Wait_Ack();
ds1307_IIC_Stop();
ds1307_IIC_Start();
ds1307_IIC_Send_Byte(0xD1);
ds1307_IIC_Wait_Ack();
dat=ds1307_IIC_Read_Byte(add);
ds1307_IIC_NAck();
ds1307_IIC_Stop();
// BCD转为16进制
temp=dat/16;
dat=dat%16;
dat=dat+temp*10;
return(dat);
}
本文使用的工程代码如下: