CSDN
网站,任何其他网站,未注明来源,见此内容均为盗链和爬取,请多多尊重和支持原创!https://github.com/lamik/DS1307_RTC_STM32_HAL
基于STM32CubeMX配置工程,当然不局限与STM32其他型号的芯片的使用,只要是stm32芯片都可以使用该源文件,在任意一款STM32型号的单片机上进行驱动移植使用,方便项目移植,减少不必要的重复开发工作。
由于工程默认配置的外部中断引脚,没有配置上下拉,中断引脚输出浮空状态,浮空状态认为是处于高电平一直处于触发状态,个人使用的话可以配置为上下拉状态,以及通过外部上下拉电阻,将中断引脚至于一个确定电平状态,然后通过上升沿或下降沿触发中断,调用 I2C DMA数据接收,这种用于主动方式来获取时间。
以上配置可以根据个人需求进行引脚切换,以及外设选择。
MicroLib
选项。#include "stdio.h"
/*可调用printf*/
int fputc(int ch,FILE *f)
{
/*&huart1指的是串口1,如果用别的串口就修改数字*/
HAL_UART_Transmit(&huart1 , (uint8_t *)&ch , 1 , 1000);
return ch;
}
/*
* DS1307.c
*
* The MIT License.
* Created on: 4.09.2019
* Author: Mateusz Salamon
* Contact: [email protected]
*
* Website: https://msalamon.pl/dalsze-zmagania-z-rtc-ds1307-i-pcf8563-na-stm32/
* GitHub: https://github.com/lamik/DS1307_RTC_STM32_HAL
*/
#include "DS1307.h"
I2C_HandleTypeDef *hi2c_ds1307;
uint8_t Ds1307Buffer[7];
void DS1307_SetControlRegister(uint8_t Value)
{
Value &= 0x93;// Put zeros where zero is needed 0b10010011
HAL_I2C_Mem_Write(hi2c_ds1307, DS1307_ADDRESS, DS1307_REG_CONTROL, 1, &Value, 1, DS1307_I2C_TIMEOUT);
}
void DS1307_GetControlRegister(uint8_t *Value)
{
HAL_I2C_Mem_Read(hi2c_ds1307, DS1307_ADDRESS, DS1307_REG_CONTROL, 1, Value, 1, DS1307_I2C_TIMEOUT);
}
void WriteBitToControlRegister(uint8_t BitNumber, uint8_t Value)
{
uint8_t tmp;
if(Value>1) Value = 1;
DS1307_GetControlRegister(&tmp);
tmp &= ~(1<<BitNumber);
tmp |= (Value<<BitNumber);
DS1307_SetControlRegister(tmp);
}
void DS1307_SQWEnable(uint8_t Enable)
{
WriteBitToControlRegister(DS1307_CONTROL_SQUARE_WAVE_ENABLE, Enable);
}
void DS1307_SQWRateSelect(uint8_t Rate)
{
uint8_t tmp;
if(Rate>3) Rate = 3;
DS1307_GetControlRegister(&tmp);
tmp &= ~(3<<DS1307_CONTROL_RATE_SELECT_0);
tmp |= (Rate<<DS1307_CONTROL_RATE_SELECT_0);
DS1307_SetControlRegister(tmp);
}
void DS1307_OutputControl(uint8_t Enable)
{
WriteBitToControlRegister(DS1307_CONTROL_OUTPUT_CONTROL, Enable);
}
void DS1307_ClockHalt(uint8_t Enable)
{
uint8_t tmp;
if(Enable>1) Enable = 1;
HAL_I2C_Mem_Read(hi2c_ds1307, DS1307_ADDRESS, DS1307_REG_SECONDS, 1, &tmp, 1, DS1307_I2C_TIMEOUT);
tmp &= ~(1<<7);
tmp |= (Enable<<7);
HAL_I2C_Mem_Write(hi2c_ds1307, DS1307_ADDRESS, DS1307_REG_SECONDS, 1, &tmp, 1, DS1307_I2C_TIMEOUT);
}
uint8_t bcd2dec(uint8_t BCD)
{
return (((BCD & 0xF0)>>4) *10) + (BCD & 0xF);
}
uint8_t dec2bcd(uint8_t DEC)
{
return ((DEC / 10)<<4) + (DEC % 10);
}
int dayofweek(int Day, int Month, int Year)
{
int Y, C, M, N, D;
M = 1 + (9 + Month) % 12;
Y = Year - (M > 10);
C = Y / 100;
D = Y % 100;
N = ((13 * M - 1) / 5 + D + D / 4 + 6 * C + Day + 5) % 7;
return (7 + N) % 7;
}
void DS1307_SetDateTime(RTCDateTime *DateTime)
{
uint8_t tmp[7];
if(DateTime->Second > 59) DateTime->Second = 59;
if(DateTime->Minute > 59) DateTime->Minute = 59;
if(DateTime->Hour > 23) DateTime->Hour = 23;
if(DateTime->Day > 31) DateTime->Day = 31;
if(DateTime->Month > 12) DateTime->Month = 12;
if(DateTime->Year> 2099) DateTime->Year = 2099;
tmp[0] = dec2bcd(DateTime->Second);
tmp[1] = dec2bcd(DateTime->Minute);
tmp[2] = dec2bcd(DateTime->Hour);
tmp[3] = dayofweek(DateTime->Day, DateTime->Month, DateTime->Year) + 1;
tmp[4] = dec2bcd(DateTime->Day);
tmp[5] = dec2bcd(DateTime->Month);
tmp[6] = dec2bcd(DateTime->Year - 2000);
HAL_I2C_Mem_Write(hi2c_ds1307, DS1307_ADDRESS, DS1307_REG_TIME, 1, tmp, 7, DS1307_I2C_TIMEOUT);
}
void DS1307_CalculateDateTime(RTCDateTime *DateTime)
{
DateTime->Second = bcd2dec(Ds1307Buffer[0]);
DateTime->Minute = bcd2dec(Ds1307Buffer[1]);
DateTime->Hour = bcd2dec(Ds1307Buffer[2] & 0x3F);
DateTime->DayOfWeek = Ds1307Buffer[3];
DateTime->Day = bcd2dec(Ds1307Buffer[4]);
DateTime->Month = bcd2dec(Ds1307Buffer[5] & 0x1F);
DateTime->Year = 2000 + bcd2dec(Ds1307Buffer[6]);
}
#ifdef DS1307_USE_DMA
void DS1307_ReceiveDateTimeDMA(void)
{
HAL_I2C_Mem_Read_DMA(hi2c_ds1307, DS1307_ADDRESS, DS1307_REG_TIME, 1, Ds1307Buffer, 7);
}
#else
void DS1307_GetDateTime(RTCDateTime *DateTime)
{
HAL_I2C_Mem_Read(hi2c_ds1307, DS1307_ADDRESS, DS1307_REG_TIME, 1, Ds1307Buffer, 7, DS1307_I2C_TIMEOUT);
DS1307_CalculateDateTime(DateTime);
}
#endif
void DS1307_ReadRAM(uint8_t Address, uint8_t *Value, uint8_t Length)
{
if((Address < DS1307_REG_RAM_START) || (Address > DS1307_REG_RAM_END)) return;
if((Address + Length + DS1307_REG_RAM_START) > DS1307_REG_RAM_END) return;
HAL_I2C_Mem_Read(hi2c_ds1307, DS1307_ADDRESS, Address, 1, Value, Length, DS1307_I2C_TIMEOUT);
}
void DS1307_WriteRAM(uint8_t Address, uint8_t *Value, uint8_t Length)
{
if((Address < DS1307_REG_RAM_START) || (Address > DS1307_REG_RAM_END)) return;
if((Address + Length + DS1307_REG_RAM_START) > DS1307_REG_RAM_END) return;
HAL_I2C_Mem_Write(hi2c_ds1307, DS1307_ADDRESS, Address, 1, Value, Length, DS1307_I2C_TIMEOUT);
}
void DS1307_Init(I2C_HandleTypeDef *hi2c)
{
hi2c_ds1307 = hi2c;
DS1307_SQWRateSelect(SQW_RATE_1HZ);
DS1307_SQWEnable(1);
DS1307_ClockHalt(0);
// Ds1307Buffer[0] = 0x00; // 初始化为写入ds1307的起始地址
// Ds1307Buffer[1] = 0x80; // 控制寄存器,启用时钟输出
// HAL_I2C_Master_Transmit_DMA(hi2c_ds1307, DS1307_ADDRESS, Ds1307Buffer, 2);
// HAL_Delay(10); // 等待数据传输完成
}
void DS1307_ReadTime(I2C_HandleTypeDef *hi2c,uint8_t *time_data)
{
hi2c_ds1307 = hi2c;
Ds1307Buffer[0] = 0x00; // 读取ds1307的起始地址
HAL_I2C_Master_Transmit_DMA(hi2c_ds1307, DS1307_ADDRESS, Ds1307Buffer, 1);
HAL_I2C_Master_Receive_DMA(hi2c_ds1307, DS1307_ADDRESS, time_data, 7);
HAL_Delay(10); // 等待数据传输完成
}
/*
* DS1307.h
*
* The MIT License.
* Created on: 4.09.2019
* Author: Mateusz Salamon
* Contact: [email protected]
*
* Website: https://msalamon.pl/dalsze-zmagania-z-rtc-ds1307-i-pcf8563-na-stm32/
* GitHub: https://github.com/lamik/DS1307_RTC_STM32_HAL
*/
#ifndef __DS1307_H__
#define __DS1307_H__
// Uncomment when you are using DMA reading
#include "main.h"
#define DS1307_USE_DMA
#define DS1307_ADDRESS (0x68<<1) //ds1307设备地址
#define DS1307_I2C_TIMEOUT 100
#define DS1307_REG_TIME 0x00
#define DS1307_REG_SECONDS 0x00
#define DS1307_REG_MINUTES 0x01
#define DS1307_REG_HOURS 0x02
#define DS1307_REG_DAY 0x03
#define DS1307_REG_DATE 0x04
#define DS1307_REG_MONTH 0x05
#define DS1307_REG_YEAR 0x06
#define DS1307_REG_CONTROL 0x07
#define DS1307_REG_RAM_START 0x08
#define DS1307_REG_RAM_END 0x3F
//
// Controll register 0x07
//
#define DS1307_CONTROL_OUTPUT_CONTROL 7
#define DS1307_CONTROL_SQUARE_WAVE_ENABLE 4
#define DS1307_CONTROL_RATE_SELECT_1 1
#define DS1307_CONTROL_RATE_SELECT_0 0
typedef enum
{
SQW_RATE_1HZ = 0,
SQW_RATE_4096HZ = 1,
SQW_RATE_8192HZ = 2,
SQW_RATE_32768HZ = 3
}SQW_Rate;
typedef struct
{
uint16_t Year;
uint8_t Month;
uint8_t Day;
uint8_t Hour;
uint8_t Minute;
uint8_t Second;
uint8_t DayOfWeek;
}RTCDateTime;
void DS1307_SQWEnable(uint8_t Enable);
void DS1307_SQWRateSelect(uint8_t Rate);
void DS1307_OutputControl(uint8_t Enable);
void DS1307_ClockHalt(uint8_t Enable);
void DS1307_ReadRAM(uint8_t Address, uint8_t *Value, uint8_t Length);
void DS1307_WriteRAM(uint8_t Address, uint8_t *Value, uint8_t Length);
void DS1307_SetDateTime(RTCDateTime *DateTime);
#ifdef DS1307_USE_DMA
void DS1307_ReceiveDateTimeDMA(void); // Use in DS1307 Interrupt handler
void DS1307_CalculateDateTime(RTCDateTime *DateTime); // Use in DMA Complete Receive interrupt
#else
void DS1307_GetDateTime(RTCDateTime *DateTime); // Use in blocking/interrupt mode in DS1307_INT EXTI handler
#endif
void DS1307_Init(I2C_HandleTypeDef *hi2c);
#endif
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "dma.h"
#include "i2c.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "DS1307.h"
#include "stdio.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
RTCDateTime r; // Date and Time variable
uint8_t Message[32]; // UART message
uint8_t MessageSize;
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
// RTCDateTime *tm;
/* 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_DMA_Init();
MX_USART1_UART_Init();
MX_I2C1_Init();
/* USER CODE BEGIN 2 */
DS1307_Init(&hi2c1);
uint32_t TimerUART = HAL_GetTick();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
if ((HAL_GetTick() - TimerUART) > 1000)
{
MessageSize = sprintf(Message, "%02d:%02d:%02d\n\r", r.Hour, r.Minute, r.Second);
// MessageSize = sprintf(Message, "%02d:%02d:%02d\n\r", tm->Hour, tm->Minute, tm->Second);
HAL_UART_Transmit(&huart1, Message, MessageSize, 1000);
// printf("Time:%s \r\n",time_data);
TimerUART = HAL_GetTick();
HAL_GPIO_TogglePin(GPIOE, LED_Pin);
}
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
#ifdef DS1307_USE_DMA
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == DS1307_INT_Pin)
{
DS1307_ReceiveDateTimeDMA();
}
}
void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c)
{
DS1307_CalculateDateTime(&r);
}
#else
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == DS1307_INT_Pin)
{
DS1307_GetDateTime(&r);
printf("EXTI trigger! \r\n");
}
}
#endif
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
CSDN
网站,任何其他网站,未注明来源,见此内容均为盗链和爬取,请多多尊重和支持原创!链接: https://pan.baidu.com/s/192KP5ozCzGFGhtzUAyuUhQ
提取码: p7j7