1. 程式人生 > >基於STM32F1的時鐘晶片DS1302驅動

基於STM32F1的時鐘晶片DS1302驅動

目錄

DS1302.h原始碼

/**
  ******************************************************************************
  * @file    DS1302.h
  * @author  Velscode
  * @email   [email protected]
  * @version 學習完全版 1.0
  * @brief   基於STM32F1x的時鐘晶片DS1302驅動
  ******************************************************************************
  */
 
#ifndef __DS1302_H
#define __DS1302_H

/* 標頭檔案   ------------------------------------------------------------------ */
#include "stm32f10x.h"  
#include "delay.h" 

/* 引腳配置 ------------------------------------------------------------------ */
#define DS1302_IO_CLOCK     RCC_APB2Periph_GPIOC    //使用到的IO口時鐘源,多個可用或|連線

#define DS1302_CLK_GPIO     GPIOC                   //CLK線
#define DS1302_CLK_PIN      GPIO_Pin_0              
#define DS1302_CLK          PCout(0)

#define DS1302_DIO_GPIO     GPIOC                   //DIO線
#define DS1302_DIO_PIN      GPIO_Pin_1              
#define DS1302_DATIN        PCin(1)
#define DS1302_DATOUT       PCout(1)

#define DS1302_RST_GPIO     GPIOC                   //RST線
#define DS1302_RST_PIN      GPIO_Pin_2
#define DS1302_RST          PCout(2)

/* 暫存器地址   -------------------------------------------------------------- */
#define DS1302_REG_SEC          0x80        //秒資料地址  
#define DS1302_REG_MIN          0x82        //分資料地址  
#define DS1302_REG_HR           0x84        //時資料地址  
#define DS1302_REG_DATE         0x86        //日資料地址  
#define DS1302_REG_MONTH        0x88        //月資料地址  
#define DS1302_REG_DAY          0x8a        //星期幾資料地址  
#define DS1302_REG_YEAR         0x8c        //年資料地址  
#define DS1302_REG_CONTROL      0x8e        //防寫暫存器地址  
#define DS1302_REG_CHARGER      0x90        //涓流充電暫存器

/* 全域性變數 ------------------------------------------------------------------ */

/* 函式宣告 ------------------------------------------------------------------ */
void DS1302_Init(void); //初始化DS1302

void Ds1302_WriteReg( unsigned char address, unsigned char dat );
unsigned char DS1302_ReadReg(unsigned char address);

unsigned char DS1302_Get_Sec  ( void );
unsigned char DS1302_Get_Min  ( void );
unsigned char DS1302_Get_Hour ( void );
unsigned char DS1302_Get_Date ( void );
unsigned char DS1302_Get_Mouth( void );
unsigned char DS1302_Get_Day  ( void );
unsigned char DS1302_Get_Year ( void );

void DS1302_Set_Sec  ( unsigned char val );
void DS1302_Set_Min  ( unsigned char val );
void DS1302_Set_Hour ( unsigned char val );
void DS1302_Set_Date ( unsigned char val );
void DS1302_Set_Mouth( unsigned char val );
void DS1302_Set_Day  ( unsigned char val );
void DS1302_Set_Year ( unsigned char val );


#endif /* __DS1302_H */
/* End of File ------------------------------------------------------------- */

DS1302.c原始碼

/**
  ******************************************************************************
  * @file    DS1302.c
  * @author  Velscode ([email protected])
  * @version 學習完全版 1.0
  * @brief   基於STM32F1x的時鐘晶片DS1302驅動
  ******************************************************************************
  */
  
#include "DS1302.h"

/* 巨集定義 ------------------------------------------------ */

/* 內部函式宣告 ------------------------------------------ */
void DS1302_Config_DIO_Input(void);
void DS1302_Config_DIO_Output(void);
  
/**
  **********************************************************
  * 函式名稱:DS1302_Init
  * 功    能:初始化IO口
  * 備    注:所有IO引數已使用巨集定義替換,只需要更改標頭檔案即可    
  **********************************************************
  */
void DS1302_Init(void)  
{  
    GPIO_InitTypeDef GPIO_InitStructure;  
    RCC_APB2PeriphClockCmd(DS1302_IO_CLOCK, ENABLE);  
    
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   //配置IO速度
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;    //配置IO輸出模式
   
    //CLK  
    GPIO_InitStructure.GPIO_Pin =DS1302_CLK_PIN;        
    GPIO_Init(DS1302_CLK_GPIO, &GPIO_InitStructure);  
      
    //DIO  
    GPIO_InitStructure.GPIO_Pin =DS1302_DIO_PIN;          
    GPIO_Init(DS1302_DIO_GPIO, &GPIO_InitStructure);  
    
    //RST  
    GPIO_InitStructure.GPIO_Pin =DS1302_RST_PIN;        
    GPIO_Init(DS1302_RST_GPIO, &GPIO_InitStructure);
    
    //設定為24小時工作制
    
}

/**
  **********************************************************
  * 函式名稱:DS1302_Config_DIO_Input
  * 功    能:將DIO口配置為輸入模式,用於讀取資料  
  **********************************************************
  */
void DS1302_Config_DIO_Input(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    //IO  
    GPIO_InitStructure.GPIO_Pin =GPIO_Pin_1;        
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(GPIOC, &GPIO_InitStructure);  
}

/**
  **********************************************************
  * 函式名稱:DS1302_Config_DIO_Output
  * 功    能:將DIO口配置為輸出模式,用於寫入資料  
  **********************************************************
  */
void DS1302_Config_DIO_Output(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    //IO  
    GPIO_InitStructure.GPIO_Pin =GPIO_Pin_1;        
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(GPIOC, &GPIO_InitStructure);  
}

/**
  **********************************************************
  * 函式名稱:DS1302_SPI_ReadByte
  * 功    能:模擬SPI通訊讀取一個位元組
  * 返    回:讀取到的位元組
  **********************************************************
  */
unsigned char DS1302_SPI_ReadByte(void)  
{  
    unsigned char i = 0, data = 0;
    
    DS1302_Config_DIO_Input();    //DIO配置為輸入模式
    
    for(i = 0; i <8; i++)
    {  
        data = data >> 1;  
        
        if(DS1302_DATIN == 1)
            data = data | 0x80;
        
        DS1302_CLK = 1;  
        DS1302_CLK = 0;
    }  

    return data;  
}

/**
  **********************************************************
  * 函式名稱:DS1302_SPI_WriteByte
  * 功    能:模擬SPI通訊寫入一個位元組
  * 參    數:dat 待寫入的位元組
  **********************************************************
  */  
void DS1302_SPI_WriteByte(u8 dat)  
{  
    u8 i = 0, data = dat;  
    
    DS1302_Config_DIO_Output();  
    
    for(i = 0; i < 8; i++)  
    {  
        DS1302_DATOUT = data&0x01;  //將資料送到IO口
     
        DS1302_CLK = 1;             //拉高時鐘,保持詩句穩定,可以延時100us
        DS1302_CLK = 0;             //拉低時鐘,準備傳輸下一位
        
        data = data >> 1;  
    }  
    
    DS1302_DATOUT = 1;              //
}  

/**
**********************************************************
* 函式名稱:DS1302_ReadReg
* 功    能:讀取DS1302暫存器中的值
* 參    數:address 暫存器的地址(無須刻意加1,軟體實現)
* 返    回:目標暫存器中的值
**********************************************************
*/
unsigned char DS1302_ReadReg(unsigned char address)  
{  
    unsigned char data = 0; 

    DS1302_CLK = 0;   
    DS1302_RST = 1; 
    
    DS1302_SPI_WriteByte(address|0x01); //讀取地址需要與0x01相或,最低為變成1  
    data = DS1302_SPI_ReadByte();  
    
    DS1302_CLK = 1;  
    DS1302_RST = 0;  
    
    return data;  
}

/**
**********************************************************
* 函式名稱:Ds1302_WriteReg
* 功    能:向DS1302暫存器中寫入一個值
* 參    數:address 暫存器的地址
* 參    數:dat     待寫入的值
**********************************************************
*/
void Ds1302_WriteReg( unsigned char address, unsigned char dat )  
{    
    DS1302_CLK = 0;  
    DS1302_RST = 1;  
    
    DS1302_SPI_WriteByte(address);  
    DS1302_SPI_WriteByte(dat);  
    
    DS1302_CLK = 1;  
    DS1302_RST = 0;  
}


/**
**********************************************************
* 函式名稱:DS1302_Get_Sec
* 功    能:獲取秒
* 返    回:一個整數,當前秒的值
*
* 80H  Bit  7  |  6  5  4   | 3  2  1  0 | 範圍
*           CH | 10 Seconds |   Seconds  | 00-59
*                 秒 - 十位    秒 - 個位
**********************************************************
*/
unsigned char DS1302_Get_Sec( void )
{
    unsigned char val = DS1302_ReadReg(DS1302_REG_SEC);
    
    val = ((val >> 4) &0x07 ) * 10 + ( val & 0x0F ); //把BCD碼轉換為實際的數值
    //      取高4位 中的 低3位的值      取低四位的值
    return val;
}

/**
**********************************************************
* 函式名稱:DS1302_Get_Min
* 功    能:獲取分
* 返    回:一個整數,當前分的值
*
* 82H  Bit  7  6  5  4 | 3  2  1  0 | 範圍
*           10 Minutes |   Minutes  | 00-59
**********************************************************
*/
unsigned char DS1302_Get_Min( void )
{
    unsigned char val = DS1302_ReadReg(DS1302_REG_MIN);
    
    val = (val >> 4) * 10 + (val & 0x0F);
    
    return val;
}

/**
********************************************************************
* 函式名稱:DS1302_Get_Hour
* 功    能:獲取小時
* 返    回:一個整數,當前小時的值
*
* 84H  Bit     7  | 6 |   5     |   4    | 3  2  1  0 | 範圍
*           12/24 | 0 |  10/AP  |10Hours |    Hours   | 1-12或0-24
* 備    注:當BIT7=1時為12小時制,此時,BIT=1代表PM
*          當BIT7=0時為24小時制,BIT5表示小時十位的數字
*          本程式未支援12小時制
*********************************************************************
*/
unsigned char DS1302_Get_Hour( void )
{
    unsigned char val = DS1302_ReadReg(DS1302_REG_HR);
    
    val =((val >> 4) & 0x03) * 10 + (val & 0x0F);
    
    return val;
}

/**
********************************************************************
* 函式名稱:DS1302_Get_Date
* 功    能:獲取日的值
* 返    回:一個整數,當前日的值
*
* 8+H  Bit     7  6 | 5  4   | 3  2  1  0 |          範圍
*              0  0 | 10DATE |    DATE    |01-28/29或01-30或01-31
*********************************************************************
*/
unsigned char DS1302_Get_Date( void )
{
    unsigned char val = DS1302_ReadReg(DS1302_REG_DATE);
    
    val =(val >> 4) * 10 + (val & 0x0F);
    
    return val;
}

/**
********************************************************************
* 函式名稱:DS1302_Get_Mouth
* 功    能:獲取月份
* 返    回:一個整數,當前月份的值
*
* 88H  Bit    7  6  5 |    4     | 3  2  1  0 | 範圍
*             0  0  0 | 10Mouths |   Mouths   | 01-12
*********************************************************************
*/
unsigned char DS1302_Get_Mouth( void )
{
    unsigned char val = DS1302_ReadReg(DS1302_REG_MONTH);
    
    val =(val >> 4) * 10 + (val & 0x0F);
    
    return val;
}

/**
********************************************************************
* 函式名稱:DS1302_Get_Day
* 功    能:獲取星期幾
* 返    回:一個整數,當前星期幾的值
*
* 88H  Bit    7  6  5  4  3 | 2  1  0 | 範圍
*             0  0  0  0  0 |   DAY   | 01-07
*********************************************************************
*/
unsigned char DS1302_Get_Day( void )
{
    return DS1302_ReadReg(DS1302_REG_DAY); //BCD碼等於真實值,無須轉換
}

/**
********************************************************************
* 函式名稱:DS1302_Get_Day
* 功    能:獲取星期幾
* 返    回:一個整數,當前星期幾的值
*
* 88H  Bit    7  6  5  4 | 3  2  1  0 | 範圍
*               10YEAR   |    YEAR    | 00-99
*********************************************************************
*/
unsigned char DS1302_Get_Year( void )
{
    unsigned char val = DS1302_ReadReg(DS1302_REG_YEAR);
    
    val =(val >> 4) * 10 + (val & 0x0F);
    
    return val;
}


void DS1302_Set_Sec  ( unsigned char val )
{
    Ds1302_WriteReg( DS1302_REG_CONTROL, 0x00 );
    Ds1302_WriteReg( DS1302_REG_SEC, ((val/10)<<4)+val%10 );
    Ds1302_WriteReg( DS1302_REG_CONTROL, 0x80 );
}
void DS1302_Set_Min  ( unsigned char val )
{
    Ds1302_WriteReg( DS1302_REG_CONTROL, 0x00 );
    Ds1302_WriteReg( DS1302_REG_MIN, ((val/10)<<4)+val%10 );
    Ds1302_WriteReg( DS1302_REG_CONTROL, 0x80 );
}
void DS1302_Set_Hour ( unsigned char val )
{
    Ds1302_WriteReg( DS1302_REG_CONTROL, 0x00 );
    Ds1302_WriteReg( DS1302_REG_HR, ((val/10)<<4)+val%10 );
    Ds1302_WriteReg( DS1302_REG_CONTROL, 0x80 );
}
void DS1302_Set_Date ( unsigned char val )
{
    Ds1302_WriteReg( DS1302_REG_CONTROL, 0x00 );
    Ds1302_WriteReg( DS1302_REG_DATE, ((val/10)<<4)+val%10 );
    Ds1302_WriteReg( DS1302_REG_CONTROL, 0x80 );
}
void DS1302_Set_Mouth( unsigned char val )
{
    Ds1302_WriteReg( DS1302_REG_CONTROL, 0x00 );
    Ds1302_WriteReg( DS1302_REG_MONTH, ((val/10)<<4)+val%10 );
    Ds1302_WriteReg( DS1302_REG_CONTROL, 0x80 );
}
void DS1302_Set_Day  ( unsigned char val )
{
    Ds1302_WriteReg( DS1302_REG_CONTROL, 0x00 );
    Ds1302_WriteReg( DS1302_REG_DAY, val );
    Ds1302_WriteReg( DS1302_REG_CONTROL, 0x80 );
}
void DS1302_Set_Year ( unsigned char val )
{
    Ds1302_WriteReg( DS1302_REG_CONTROL, 0x00 );
    Ds1302_WriteReg( DS1302_REG_YEAR, ((val/10)<<4)+val%10 );
    Ds1302_WriteReg( DS1302_REG_CONTROL, 0x80 );
}



/* End of File ------------------------------------------------------------- */