stm32-DS1302时钟模块驱动

DS1302是时钟芯片

1. DS1302芯片简介

DS1302的寄存器地址定义如下:

 

stm32-DS1302时钟模块驱动_第1张图片

单字节读写时序如下图,均为上升沿触发:

stm32-DS1302时钟模块驱动_第2张图片

 由于DS1302时钟芯片不是常用的SPI协议,与SPI协议很像,所以需要初始化普通GPIO口手工实现该协议通信。

2. cubemx设置

设置分别连接DS1302的CE、SCLK、Data口的GPIO,PB8\PB9\PB10:

stm32-DS1302时钟模块驱动_第3张图片

3. keil开发

打开gpio.h文件,定义结构体和预处理:

#define W_SECOND 0x80
#define W_MINUTE 0x82
#define W_HOUR   0x84
#define W_DAY    0x86
#define W_MONTH  0x88
#define W_WEEK   0x8A
#define W_YEAR   0x8C
#define W_CONTR  0x8E

#define R_SECOND 0x81
#define R_MINUTE 0x83
#define R_HOUR   0x85
#define R_DAY    0x87
#define R_MONTH  0x89
#define R_WEEK   0x8B
#define R_YEAR   0x8D
#define R_CONTR  0x8F

#define RST_L     HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_RESET)
#define RST_H     HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET)
#define CLK_L     HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, GPIO_PIN_RESET)
#define CLK_H     HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, GPIO_PIN_SET)
#define DATA_L    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET)
#define DATA_H    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET)

#define DATA_READ HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_10)

typedef struct {
	uint8_t year;
	uint8_t week;
	uint8_t month;
	uint8_t day;
	uint8_t hour;
	uint8_t minute;
	uint8_t second;
}timeNow_t;

由于数据发送和接受是共用PB10,编写数据写GPIO和读GPIO的初始化:

static void DS1302_Data_Write_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};
	  /*Configure GPIO pin : PB10 */
  GPIO_InitStruct.Pin = GPIO_PIN_10;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
static void DS1302_Data_Read_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};
	  /*Configure GPIO pin : PB10 */
  GPIO_InitStruct.Pin = GPIO_PIN_10;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}

定义读和写寄存器的操作函数:

void DS1302_Single_Byte_Write(uint8_t data)
{
	DS1302_Data_Write_Init();
	CLK_L;
	for(int i=0;i<8;i++)
	{
		CLK_L;
		if((data&0x01)==0x01)
			DATA_H;
		else
			DATA_L;
		data>>=0x01;
		CLK_H;
	}
}
void DS1302_Write_Register(uint8_t regAddress,uint8_t regData)
{
	RST_L;
	CLK_L;
	RST_H;
	DS1302_Single_Byte_Write(regAddress);
	DS1302_Single_Byte_Write(regData);
	RST_H;
}
uint8_t DS1302_Read_Register(uint8_t regAddress)
{
	RST_L;
	CLK_L;
	uint8_t regData=0x00;
	RST_H;
	DS1302_Single_Byte_Write(regAddress);
	DS1302_Data_Read_Init();
	for(int i=0;i<8;i++)
	{
		regData>>=0x01;
		CLK_H;
		CLK_L;
		HAL_Delay(1);
		if(DATA_READ==GPIO_PIN_SET)
			regData=regData|0x80;
	}
	RST_H;
	return regData;
}

 设置和读取时间函数:

void DS1302_Set_Time(uint8_t year,uint8_t week,uint8_t month,uint8_t day,uint8_t hour,uint8_t minute,uint8_t second)
{
	DS1302_Write_Register(W_CONTR,0x00);
	DS1302_Write_Register(W_YEAR,year);
	DS1302_Write_Register(W_WEEK,week);
	DS1302_Write_Register(W_MONTH,month);
	DS1302_Write_Register(W_DAY,day);
	DS1302_Write_Register(W_HOUR,hour);
	DS1302_Write_Register(W_MINUTE,minute);
	DS1302_Write_Register(W_SECOND,second);
	DS1302_Write_Register(W_CONTR,0x80);
}
timeNow_t DS1302_Read_Time(void)
{
	timeNow_t timeNow;
	timeNow.year=DS1302_Read_Register(R_YEAR);
	timeNow.week=DS1302_Read_Register(R_WEEK);
	timeNow.month=DS1302_Read_Register(R_MONTH);
	timeNow.day=DS1302_Read_Register(R_DAY);
	timeNow.hour=DS1302_Read_Register(R_HOUR);
	timeNow.minute=DS1302_Read_Register(R_MINUTE);
	timeNow.second=DS1302_Read_Register(R_SECOND);
	return timeNow;
}

显示时间:

void DS1302_Print_Time(void)
{
	timeNow_t timeNow=DS1302_Read_Time();
	printf("20%02X-%02X-%02X %02X:%02X:%02X\n",timeNow.year,timeNow.month,timeNow.day,timeNow.hour,timeNow.minute,timeNow.second);
	
}

在main函数中测试是否成功实现时钟显示:

	DS1302_Set_Time(0x22,0x07,0x08,0x07,0x11,0x36,0x09);

  while (1)
  {
		HAL_Delay(1000);
		DS1302_Print_Time();
  }

成功显示时钟:

stm32-DS1302时钟模块驱动_第4张图片

 

你可能感兴趣的:(STM32驱动,stm32,单片机,arm)