2.3.1
https://www.st.com/zh/embedded-software/stsw-stm8069.html
IAR Assembler for STMicroelectronics STM8 3.11.1
https://oshwhub.com/perseverance51/stm8s207rbt6-kai-fa-ban
基于标准库工程,当然不局限与STM8其他型号的芯片的使用,只要是stm8芯片都可以使用该源文件进行驱动,方便适配移植,减少不必要的重复开发工作。
如果是其他型号可以根据自由更换其他引脚。注意修改相关定义。
TM8S单片机-->DS1302
PC2 -->CLK
PC3-->DAT
PC4 -->RST
#ifndef __DS1302_H
#define __DS1302_H
/****************************驱动 RTC 芯片 DS1302******************************/
/* Includes ------------------------------------------------------------------*/
#include "stm8s.h"
/* Defines -------------------------------------------------------------------*/
//是否设置时间到DS1302中
#define RTC_RESET_TIME_EN 0u
#define RTC_SCK_PORT (GPIO_TypeDef *)(GPIOC)
#define RTC_SCK_PIN (GPIO_PIN_2) // PC2
#define RTC_SCK_HIGH() GPIO_WriteHigh(RTC_SCK_PORT, RTC_SCK_PIN)
#define RTC_SCK_LOW() GPIO_WriteLow (RTC_SCK_PORT, RTC_SCK_PIN)
#define RTC_IO_PORT (GPIO_TypeDef *)(GPIOC)
#define RTC_IO_PIN (GPIO_PIN_3) // PC3
#define RTC_IO_IN() GPIO_Init(RTC_IO_PORT, RTC_IO_PIN, GPIO_MODE_IN_PU_NO_IT)
#define RTC_IO_STATUS() GPIO_ReadInputPin(RTC_IO_PORT, RTC_IO_PIN)
#define RTC_IO_OUT() GPIO_Init(RTC_IO_PORT, RTC_IO_PIN, GPIO_MODE_OUT_PP_HIGH_SLOW)
#define RTC_IO_HIGH() GPIO_WriteHigh(RTC_IO_PORT, RTC_IO_PIN)
#define RTC_IO_LOW() GPIO_WriteLow (RTC_IO_PORT, RTC_IO_PIN)
#define RTC_RST_PORT (GPIO_TypeDef *)(GPIOC)
#define RTC_RST_PIN (GPIO_PIN_4) // PC4
#define RTC_RST_HIGH() GPIO_WriteHigh(RTC_RST_PORT, RTC_RST_PIN)
#define RTC_RST_LOW() GPIO_WriteLow (RTC_RST_PORT, RTC_RST_PIN)
/* Values --------------------------------------------------------------------*/
typedef struct Time
{
uint8_t year; // year 0-99
uint8_t month; // month 01-12
uint8_t day; // day 01-28,29,30,31
uint8_t week; // week 01-07
uint8_t hour; // hour 01-12 or 00-23
uint8_t minute; // minute 00-59
uint8_t second; // second 00-59
} TimeTypeDef;
static TimeTypeDef TimeBuffer; // 数据缓冲区(8421-BCD码)
/* Functions -----------------------------------------------------------------*/
void DS1302_Init ( void );
static void DS1302_WriteByte ( uint8_t byte );
static uint8_t DS1302_ReadByte ( void );
static void DS1302_WriteData ( uint8_t addr, uint8_t data );
static uint8_t DS1302_ReadData ( uint8_t addr );
TimeTypeDef DS1302_ReadTime ( void );
void DS1302_WriteTime ( TimeTypeDef *TimeDisplay );
static uint8_t DectoBCD ( uint8_t num );
static uint8_t BCDtoDec ( uint8_t num );
//static void DS1302_DLY_ms( uint16_t nCount );
static void DS1302_DLY_us( uint16_t nCount );
#endif /* __DS1302_H */
#include "ds1302.h"
/*************************************************************************
初始化
--------------------------------------------------------------------------
无参数
--------------------------------------------------------------------------
无返回值
*************************************************************************/
void DS1302_Init ( void )
{
GPIO_Init( RTC_SCK_PORT, RTC_SCK_PIN, GPIO_MODE_OUT_PP_HIGH_SLOW );
GPIO_Init( RTC_RST_PORT, RTC_RST_PIN, GPIO_MODE_OUT_PP_HIGH_SLOW );
GPIO_Init( RTC_IO_PORT, RTC_IO_PIN, GPIO_MODE_OUT_PP_HIGH_SLOW );
RTC_SCK_LOW();
RTC_IO_LOW();
RTC_RST_LOW();
}
/*************************************************************************
写一字节数据
--------------------------------------------------------------------------
byte:一字节数据
--------------------------------------------------------------------------
无返回值
*************************************************************************/
static void DS1302_WriteByte ( uint8_t byte )
{
uint8_t i;
BitStatus bit;
RTC_IO_OUT(); // IO 配置为输出模式
for ( i = 0; i < 8; i++ )
{
RTC_SCK_LOW();
bit = ( BitStatus )( byte & 0x01 );
if ( bit != RESET )
RTC_IO_HIGH();
else
RTC_IO_LOW();
RTC_SCK_HIGH();
byte >>= 1;
//DS1302_DLY_ms(1);
}
}
/*************************************************************************
读一字节数据
--------------------------------------------------------------------------
addr:地址
--------------------------------------------------------------------------
返回值:一字节数据
*************************************************************************/
static uint8_t DS1302_ReadByte ( void )
{
uint8_t i;
uint8_t data = 0;
BitStatus bit;
RTC_IO_IN(); // IO 配置为输入模式
for ( i = 0; i < 8; i++ )
{
data >>= 1;
RTC_SCK_LOW();
bit = RTC_IO_STATUS();
if ( bit != RESET )
data |= 0x80;
else
data &= 0x7F;
RTC_SCK_HIGH();
//DS1302_DLY_ms(1);
}
return data;
}
/*************************************************************************
往指定寄存器写入一字节数据
--------------------------------------------------------------------------
addr:地址 data:一字节数据
--------------------------------------------------------------------------
无返回值
*************************************************************************/
static void DS1302_WriteData ( uint8_t addr, uint8_t data )
{
// 数据传输开始
RTC_RST_LOW();
RTC_SCK_LOW();
RTC_RST_HIGH();
DS1302_WriteByte ( addr ); // 写入的地址
DS1302_WriteByte ( data ); // 写入的数据
// 数据传输结束
RTC_RST_LOW();
}
/*************************************************************************
在指定寄存器读出一字节数据
--------------------------------------------------------------------------
addr:地址
--------------------------------------------------------------------------
返回值:一字节数据
*************************************************************************/
static uint8_t DS1302_ReadData ( uint8_t addr )
{
uint8_t data;
// 数据传输开始
RTC_RST_LOW();
RTC_SCK_LOW();
RTC_RST_HIGH();
DS1302_WriteByte ( addr ); // 要读的地址
data = DS1302_ReadByte(); // 要读的数据
// 数据传输结束
RTC_RST_LOW();
return data;
}
/*************************************************************************
读时间
--------------------------------------------------------------------------
无参数
--------------------------------------------------------------------------
返回值:时间数据
*************************************************************************/
TimeTypeDef DS1302_ReadTime ( void )
{
TimeTypeDef TimeDisplay;
// 读出来的数据是 BCD 码
TimeBuffer.year = DS1302_ReadData ( 0x8D );
TimeBuffer.month = DS1302_ReadData ( 0x89 );
TimeBuffer.day = DS1302_ReadData ( 0x87 );
TimeBuffer.week = DS1302_ReadData ( 0x8B );
TimeBuffer.hour = DS1302_ReadData ( 0x85 );
TimeBuffer.minute = DS1302_ReadData ( 0x83 );
TimeBuffer.second = DS1302_ReadData ( 0x81 ); // bit7 定义为时钟暂停标志(CH)
// BCD 码转换为十进制
TimeDisplay.year = BCDtoDec ( TimeBuffer.year );
TimeDisplay.month = BCDtoDec ( TimeBuffer.month );
TimeDisplay.day = BCDtoDec ( TimeBuffer.day );
TimeDisplay.week = BCDtoDec ( TimeBuffer.week );
TimeDisplay.hour = BCDtoDec ( TimeBuffer.hour );
TimeDisplay.minute = BCDtoDec ( TimeBuffer.minute );
TimeDisplay.second = BCDtoDec ( TimeBuffer.second );
return TimeDisplay;
}
/*************************************************************************
修改时间
--------------------------------------------------------------------------
*TimeDisplay:要显示的时间(十进制)
--------------------------------------------------------------------------
无返回值
*************************************************************************/
void DS1302_WriteTime ( TimeTypeDef *TimeDisplay )
{
// 十进制转换为 BCD 码
TimeBuffer.year = DectoBCD ( TimeDisplay->year );
TimeBuffer.month = DectoBCD ( TimeDisplay->month );
TimeBuffer.day = DectoBCD ( TimeDisplay->day );
TimeBuffer.week = DectoBCD ( TimeDisplay->week );
TimeBuffer.hour = DectoBCD ( TimeDisplay->hour );
TimeBuffer.minute = DectoBCD ( TimeDisplay->minute );
TimeBuffer.second = DectoBCD ( TimeDisplay->second );
// 关闭写保护(控制寄存器:8FH、8EH bit7:保护位)
DS1302_WriteData ( 0x8E, 0x00 );
// 写入的数据是 BCD 码
DS1302_WriteData ( 0x8C, TimeBuffer.year );
DS1302_WriteData ( 0x88, TimeBuffer.month );
DS1302_WriteData ( 0x86, TimeBuffer.day );
DS1302_WriteData ( 0x8A, TimeBuffer.week );
DS1302_WriteData ( 0x84, TimeBuffer.hour );
DS1302_WriteData ( 0x82, TimeBuffer.minute );
DS1302_WriteData ( 0x80, TimeBuffer.second ); // bit7 定义为时钟暂停标志(CH)
// 开启写保护(控制寄存器:8FH、8EH bit7:保护位)
DS1302_WriteData ( 0x8E, 0x80 );
}
/*************************************************************************
十进制转BCD码
--------------------------------------------------------------------------
num:十进制数
--------------------------------------------------------------------------
返回值:BCD码
*************************************************************************/
static uint8_t DectoBCD ( uint8_t num )
{
uint8_t result;
uint8_t temp1, temp2;
temp1 = ( num / 10 ) << 4; // 十位 / 10 * 16
temp2 = num % 10; // 个位 % 10
result = temp1 + temp2;
return result;
}
/*************************************************************************
BCD码转十进制
--------------------------------------------------------------------------
num:BCD码
--------------------------------------------------------------------------
返回值:十进制
*************************************************************************/
static uint8_t BCDtoDec ( uint8_t num )
{
uint8_t result;
uint8_t temp1, temp2;
temp1 = ( num >> 4 ) * 10; // 十位 / 16 * 10
temp2 = num & 0x0F; // 个位 % 16
result = temp1 + temp2;
return result;
}
/*************************************************************************
软件延时(ms级别)
--------------------------------------------------------------------------
nCount:延时长度
--------------------------------------------------------------------------
无返回值
*************************************************************************/
//static void DS1302_DLY_ms( uint16_t nCount )
//{
// while( nCount-- )
// {
// DS1302_DLY_us( 1000 );
// }
//}
/*************************************************************************
软件延时(us级别)
--------------------------------------------------------------------------
nCount:延时长度
--------------------------------------------------------------------------
无返回值
*************************************************************************/
static void DS1302_DLY_us( uint16_t nCount )
{
nCount *= 2;
while( --nCount );
}
/**************************************************************************************
实验现象:打开串口调试助手,选择CH340对应串口号,波特率设置9600, 串口助手上会显示
printf各种数据格式输出信息。
接线说明: 1,STM8S单片机-->LED
PC7-->LED1
PC6-->LED2
---------------------------------------------------------
TM8S单片机-->DS1302
PC2 -->CLK
PC3-->DAT
PC4 -->RST
注意事项: 1、点击“Download active application”按钮,程序下载完成后,即可运行程序。
2、串口1使用的是PA4和PA5引脚,所以这两个IO口不要被占用
***************************************************************************************/
#include "stm8s.h" /* 添加库函数头文件 */
#include "delay.h"
#include "led.h"
#include "usart.h"
#include "ds1302.h"
#include //包含此头文件调用printf函数串口才能有输出
/* 主函数 */
int main( void )
{
u8 i = 0;
// 设置初始时间
// TimeTypeDef Set_Time = {23, 04, 4, 2, 23, 25, 10};
const char *WEEK[7] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
TimeTypeDef tm= {0};
uint8_t TimeSecPre;
disableInterrupts(); //关闭系统中断
//内部时钟为1分频 = 16Mhz
CLK_SYSCLKConfig( CLK_PRESCALER_HSIDIV1 );
LED_Init();
USART1_Init( 9600 ); //初始化USART1 , 并设置波特率为9600
DS1302_Init();
//是否设置时间到DS1302中
#if RTC_RESET_TIME_EN > 0u
DS1302_WriteTime( Set_Time );
#endif
enableInterrupts(); //使能系统中断
while( 1 )
{
i++;
if( i % 20 == 0 )
{
LED1_TOGGLE;
LED2_TOGGLE;
}
tm = DS1302_ReadTime();
if ( TimeSecPre != tm.second )
{
TimeSecPre = tm.second;
printf( "20%02d年%02d月%02d日 星期:%s %02d:%02d:%02d\r\n", tm.year, tm.month, tm.day,
WEEK[tm.week] , tm.hour, tm.minute, tm.second);
}
delay_ms( 10 );
}
}
//是一个宏定义;在固件库中,它的作用就是检测传递给函数的参数是否是有效的参数
void assert_failed( u8* file, u32 line )
{
while ( 1 )
{
}
}
链接: https://pan.baidu.com/s/18drnS5yPTSz79vxTBS7Brw
提取码: thdy