Jugando con Raspberry Pi (22) - Práctica de reloj de hardware DS1302

Jugando con Raspberry Pi (22) - Práctica de reloj de hardware DS1302

No sé si te has dado cuenta de que cuando usamos la computadora, excepto la primera vez que necesitamos sincronizar la hora, es decir, no hay conexión de red. Después de apagar y reiniciar la computadora, la hora de la computadora es aún precisa. Esto se debe a que hay un módulo de reloj de hardware con su propia fuente de alimentación dentro del host de la computadora.Después de escribir la hora actual en el módulo al sincronizar la hora, el módulo de reloj de hardware mantendrá automáticamente la hora actual precisa. No hay un módulo de reloj de hardware dentro de la propia Raspberry Pi, pero en algunos escenarios de demanda fuera de la red, necesitamos registrar con precisión la fecha y la hora actuales. Por ejemplo, hemos introducido muchos sensores relacionados con el clima antes. La hora exacta en ese el tiempo debe ser registrado.

1. Introducción al módulo DS1302

DS1302 es un chip de temporización de carga lenta. Tiene un reloj en tiempo real que puede calcular años, meses, días, horas, minutos, segundos, semanas y otra información, y el intervalo de tiempo disponible es entre 2000 y 2100. Además, también tiene una memoria RAM temporal de propósito general de 31*8 bits para almacenar algunos datos lógicos temporales. DS1302 adopta comunicación serial síncrona, lo que simplifica la interfaz del procesador.En teoría, además de la fuente de alimentación, la principal necesidad de conectar tres líneas para realizar la función de comunicación, a saber, línea CE, línea I/O y línea de reloj serial SCLK .

El chip DS1302 tiene 8 pines y la estructura del circuito de trabajo se muestra en la siguiente figura:

La función de cada pin es la siguiente:

DS1302 usa una palabra de comando de instrucción de 8 bits. Antes de cada comunicación, necesita usar la palabra de comando para comenzar. La estructura de la palabra de comando es la siguiente:

Como se muestra en la figura anterior, el séptimo bit es el bit de control válido para escribir. Cuando es 0, la escritura no es válida. Cuando es 1, se permite escribir. Cada vez que se transmiten datos, este bit debe establecerse a 1. Generalmente, estamos usando el comando, esto se establece a la fuerza en 1.

El sexto bit controla la función del chip, cuando es 0, significa usar los datos del reloj, y cuando es 1, significa usar los datos de RAM.

Los bits 1 a 5 son bits de selección de registro, que seleccionan el registro que se va a operar.

El bit 0 es el bit de control de lectura y escritura. Cuando es 0, significa escribir datos en el registro, y cuando es 1, significa leer datos del registro.

Conociendo la estructura de instrucciones de DS1302, para usarlo, también necesitamos tener una comprensión simple de la función del registro. En este experimento, usamos principalmente la función de reloj de DS1302. Hay 7 registros relacionados con la función de reloj. El El manual del chip da un ejemplo, de la siguiente manera:

A continuación presentamos las funciones y el uso de estos registros.

En primer lugar, hay 5 bits en la instrucción para identificar la dirección del registro que se va a operar.La figura anterior me da directamente las instrucciones de lectura y escritura para operar el registro.

La dirección del primer registro es 0b0, por lo que su instrucción de lectura es 0b1000 0001 y su instrucción de escritura es 0b1000 0000, que se convierte a hexadecimal, es decir, 0x81 y 0x80 en la figura anterior. El bit más alto CH de este registro es un bit de bandera. Podemos leer este bit después de cada encendido. Si es 1, significa que el sistema no está funcionando después de que se apaga la alimentación. Necesitamos recalibrar el tiempo. Si es 0, significa que la energía de respaldo es normal y siempre continúa funcionando normalmente. Los dígitos 4 a 6 se usan para representar los datos de diez dígitos del segundo de tiempo, y los dígitos 0 a 3 se usan para representar los datos de un dígito del segundo, porque los datos de diez dígitos del segundo son como máximo 5 y 3 dígitos binarios son suficientes.

La dirección del segundo registro es 0b1, y su bit más alto es un bit reservado, que actualmente no sirve, los bits 4 a 6 se usan para ignorar las decenas de minutos, y los bits 0 a 3 representan las de minutos. Los datos de bits son hasta 5 y 3 bits binarios son suficientes.

La dirección del tercer registro es 0b10, el bit más alto es 1, lo que significa que actualmente se usa el sistema de 12 horas, y el bit más alto es 0, lo que significa que se usa el sistema de 24 horas. El bit 6 se fija en 0 y no tiene significado. El quinto dígito está en el modo de reloj de 12 horas, 1 significa tarde, 0 significa mañana. En el modo de reloj de 24 horas, los dígitos 4 y 5 juntos representan las decenas de la hora. Los dígitos 0 a 3 representan el dígito de las unidades de la hora.

La dirección del cuarto registro es 0b11, y sus bits 7 y 6 son 0 fijos, lo que no tiene sentido. Los dígitos 5 y 4 juntos representan las decenas de la fecha, y los dígitos 0 a 3 representan las de la fecha.

La dirección del quinto registro es 0b100, y sus bits del 5 al 7 son 0 fijos, lo que no tiene sentido. El cuarto dígito representa las decenas del mes y los dígitos del 0 al 3 representan las del mes.

La dirección del sexto registro es 0b101 y sus 5 bits superiores están fijados en 0, lo que no tiene sentido. El tercer dígito indica el día de la semana.

La dirección del séptimo registro es 0b110, los 4 bits superiores representan las decenas del año, y el 4° bit representa las del año, pudiendo representar valores entre 0 y 99, es decir desde 2000 hasta 2099.

La dirección del 8º registro es 0b111, que es un registro de control. Al escribir datos, el bit más alto WP de este registro debe ser 0. Si este bit es 1, se prohibirá la operación de escritura en otros registros. Proteger.

Si desea utilizar la función RAM, los dos primeros bits de la instrucción deben ser 11, por lo que las instrucciones de lectura y escritura para el primer registro de la RAM son 0b1100 0000 o 0b1100 0001, es decir, 0xC0 y 0xC1. Hay 31 registros de almacenamiento de RAM, las direcciones son de 0x00 a 0x1F y las palabras de comando correspondientes son de 0xC0 a 0xFF.

Ya sea en modo reloj o modo RAM, DS1302 admite el uso de tren de pulsos para leer y escribir datos.El comando de tren de pulsos de reloj es 0xBF y 0xBE, y el tren de pulsos RAM es 0xFF y 0xFE. Los datos se escriben y leen secuencialmente en el orden de los registros.

Después de comprender la lógica de uso de las instrucciones y los registros, queda una cosa más por aclarar, es decir, cómo ingresar y leer datos. El pin RST se usa para controlar la lectura y escritura de datos, y RTS cambia de un nivel bajo a un nivel alto para activar un proceso de transferencia de datos.

2. Conexión experimental

En este experimento, usamos el módulo DS1302 empaquetado, como se muestra en la siguiente figura:

Entre ellos, CLK corresponde al pin SCLK, DAT es el pin de función IO y RST corresponde al pin de función CE. Elegimos los pines 16, 18 y 22 en la Raspberry Pi (código físico, correspondientes al 23, 24 y 25 del código BCM respectivamente), y las conexiones son las siguientes:

DS1302 pastel de frambuesa
CCV 3,3 V
TIERRA TIERRA
CLK GPIO23 (codificación BCM)
CUAL GPIO24 (codificación BCM)
PRIMERA GPIO25 (codificación BCM)

3. Codificación de experimentos

Ahora, solo necesitamos codificar de acuerdo con el uso del módulo presentado anteriormente, el código de muestra es el siguiente:

#coding:utf-8

import time
import RPi.GPIO
from datetime import datetime

# 使用物理编码
SCL = 16
IO = 18
RST = 22

# 数据读写的间隔
CLK_PERIOD = 0.00001

# 关闭GPIO警告
RPi.GPIO.setwarnings(False)
# 配置树莓派GPIO接口 使用物理编码
RPi.GPIO.setmode(RPi.GPIO.BOARD)

# 写入一个字节的数据
def writeByte(Byte):
    for Count in range(8):
        # 将SCL置为低电平 开启一次传输
        time.sleep(CLK_PERIOD)
        RPi.GPIO.output(SCL, 0)
        # 取一位数据进行写入
        Bit = Byte % 2
        Byte = int(Byte / 2)
        # 通过IO引脚进行写入
        time.sleep(CLK_PERIOD)
        RPi.GPIO.output(IO, Bit)
        # 将SCL置为高电平 结束一次传输
        time.sleep(CLK_PERIOD)
        RPi.GPIO.output(SCL, 1)

# 读取一个字节的数据
def readByte():
    # 将IO引脚设置为输入
    RPi.GPIO.setup(IO, RPi.GPIO.IN, pull_up_down=RPi.GPIO.PUD_DOWN)
    Byte = 0
    for Count in range(8):
        # 先将SCL重置为高电平 
        time.sleep(CLK_PERIOD)
        RPi.GPIO.output(SCL, 1)
        # 将SCL置为低电平 开启一次传输
        time.sleep(CLK_PERIOD)
        RPi.GPIO.output(SCL, 0)
        # 读取一位数据
        time.sleep(CLK_PERIOD)
        Bit = RPi.GPIO.input(IO)
        Byte |= ((2 ** Count) * Bit)
    return Byte

# 重置一些数据
def resetDS1302():
    # SCL引脚设置为输出
    RPi.GPIO.setup(SCL, RPi.GPIO.OUT, initial=0)
    # RST引脚设置为输出
    RPi.GPIO.setup(RST, RPi.GPIO.OUT, initial=0)
    # IO引脚设置为输出
    RPi.GPIO.setup(IO, RPi.GPIO.OUT, initial=0)
    # SCL和IO都置为低电平
    RPi.GPIO.output(SCL, 0)
    RPi.GPIO.output(IO, 0)
    time.sleep(CLK_PERIOD)
    # RST置为高电平
    RPi.GPIO.output(RST, 1)

# 结束操作
def endDS1302():
    # SCL引脚设置为输出
    RPi.GPIO.setup(SCL, RPi.GPIO.OUT, initial=0)
    # RST引脚设置为输出
    RPi.GPIO.setup(RST, RPi.GPIO.OUT, initial=0)
    # IO引脚设置为输出
    RPi.GPIO.setup(IO, RPi.GPIO.OUT, initial=0)
    # SCL和IO都置为低电平
    RPi.GPIO.output(SCL, 0)
    RPi.GPIO.output(IO, 0)
    time.sleep(CLK_PERIOD)
    # RST置为低电平
    RPi.GPIO.output(RST, 0)


# 进行时间校准
def setDatetime(year, month, day,  hour, minute, second, dayOfWeek):
    # 引脚重置
    resetDS1302()
    # 设置写始终数据脉冲指令
    writeByte(int("10111110", 2))

    # 开始依次写数据
    # 写入秒数据,*16的作用是把十位右移4位 下面同
    writeByte((second % 10) | int(second / 10) * 16)
    # 写入分钟数据
    writeByte((minute % 10) | int(minute / 10) * 16)
    # 写入小时数据
    writeByte((hour % 10) | int(hour / 10) * 16)
    # 写入日期数据
    writeByte((day % 10) | int(day / 10) * 16)
    # 写入月份数据
    writeByte((month % 10) | int(month / 10) * 16)
    # 写入星期数据
    writeByte(dayOfWeek)
    # 写入年份数据
    writeByte((year % 100 % 10) | int(year % 100 / 10) * 16)
    # 结束数据写入
    writeByte(int("00000000", 2))
    # 结束任务
    endDS1302()

# 获取DS1302硬件时钟实践
def getDatetime():
    # 重置引脚
    resetDS1302()
    # 0xBF指令,开始时钟脉冲串读取数据
    writeByte(int("10111111", 2))

    Data = ""
    
    # 依次读取
    # 先读出秒数据
    Byte = readByte()
    second = (Byte % 16) + int(Byte / 16) * 10
    # 分钟数据
    Byte = readByte()
    minute = (Byte % 16) + int(Byte / 16) * 10
    # 小时数据
    Byte = readByte()
    hour = (Byte % 16) + int(Byte / 16) * 10
    # 日期数据
    Byte = readByte()
    day = (Byte % 16) + int(Byte / 16) * 10
    # 月份数据
    Byte = readByte()
    month = (Byte % 16) + int(Byte / 16) * 10
    # 星期数据
    Byte = readByte()
    day_of_week = (Byte % 16)
    # 年数据
    Byte = readByte()
    year = (Byte % 16) + int(Byte / 16) * 10 + 2000

    # 结束任务
    endDS1302()
    return datetime(year, month, day, hour, minute, second)

# 时间格式化
def format_time(dt):
    if dt is None:
        return ""
    fmt = "%m/%d/%Y %H:%M"
    return dt.strftime(fmt)
    
def parse_time(s):
    fmt = "%m/%d/%Y %H:%M"
    return datetime.strptime(s, fmt)



# 初始化工作

resetDS1302()

# 写保护已关闭。
writeByte(int("10001110", 2))
# 结束指令执行
writeByte(int("00000000", 2))
# 涓流充电模式被关闭。
writeByte(int("10010000", 2))
# 结束指令执行
writeByte(int("00000000", 2))
#结束任务
endDS1302()
        

current = datetime.now()

year = current.year
month = current.month
day = current.day
hour = current.hour
minute = current.minute
second = current.second
week = current.weekday()

setDatetime(year,month,day,hour,minute,second,week)

while True:
    time.sleep(1)
    dt = getDatetime()
    print(dt)


En el código de ejemplo anterior, ya sea leyendo o escribiendo datos, todos usamos el modo de comunicación del tren de pulsos del reloj, por lo que solo necesitamos configurar el comando una vez, y los datos requeridos se pueden leer a pedido, lo que es muy conveniente Ejecute el código anterior en Raspberry Pi, el efecto es el que se muestra a continuación:

4. Piénsalo

Siguiendo la idea anterior, ¿se puede cambiar a un método de comunicación de tren de pulsos sin reloj para obtener información de fecha y hora? ¡Intentalo!

Concéntrese en la tecnología, comprenda el amor, esté dispuesto a compartir, sea un amigo

Pregunta rápida: 316045346

{{o.nombre}}
{{m.nombre}}

Supongo que te gusta

Origin my.oschina.net/u/2340880/blog/5330619
Recomendado
Clasificación