nonocast / hello-zhulaoshi

朱有鹏单片机和嵌入式课程笔记
6 stars 0 forks source link

单片机实践 (Part 2) #3

Open nonocast opened 3 years ago

nonocast commented 3 years ago

1.14 RTC实时时钟

SPI

DS1302

rtc.h

#ifndef __RTC_H_
#define __RTC_H_

#include <stdio.h>
#include <stdlib.h>
#include <8051.h>

typedef unsigned int word;
typedef unsigned char byte;

// 定义DS1302的引脚
#define DSIO  P3_4
#define RST   P3_5
#define SCLK  P3_6
#define _nop_() __asm NOP __endasm

char* getRTC();
byte read(byte addr);

#endif

rtc.c

#include "rtc.h"

// 秒分时日月周年
// __code让sdcc将数组放在ROM中,而不是默认的RAM
__code byte READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d};

char *getRTC() {
  byte time[7];

  byte i = 0;
  // 读取7个字节的时钟信号:秒分时日月周年
  for (i = 0; i < 7; ++i) {
    time[i] = read(READ_RTC_ADDR[i]);
  }

  char result[30];
  // BCD编码: 只有0-9,没有A-F, 通过16进制表示10进制, 0x21表达十进制21
  sprintf(result, "%x %x %x %x %x %x %x\r\n", time[0], time[1], time[2],
          time[3], time[4], time[5], time[6]);
  return result;
}

byte read(byte addr) {
  byte result = 0;
  byte i = 0;
  byte bit = 0;

  // initial
  RST = 0;
  _nop_();

  SCLK = 0;
  _nop_();

  RST = 1;
  _nop_();

  for (i = 0; i < 8; ++i) {
    DSIO = addr & 0x01;
    addr >>= 1;
    SCLK = 1;
    _nop_();
    SCLK = 0;
    _nop_();
  }

  _nop_();

  for (i = 0; i < 8; ++i) {
    bit = DSIO;
    result |= bit << i;
    SCLK = 1;
    _nop_();
    SCLK = 0;
    _nop_();
  }

  RST = 0;
  _nop_();
  SCLK = 1;
  _nop_();
  DSIO = 0;
  _nop_();
  DSIO = 1;
  _nop_();
  return result;
}

app.c

#include <8051.h>
#include <stdbool.h>
#include <stdlib.h>
#include <time.h>

#include "rtc.h"

typedef unsigned int word;
typedef unsigned char byte;

void delay(word i);
void init();
void loop();
void sendByte(byte);
void sendString(char *string);

void main() {
  init();
  while (true) {
    loop();
  }
}

void init() {
  SCON = 0x50; // 0b 0101 0000
  TMOD = 0x20; // set timer1 as 8-bit auto reload mode
  PCON = 0x80;
  TH1 = TL1 = 0xf3;

  TR1 = 1; // timer1 start run
  ES = 1;  // enable uart interrupt
  EA = 1;  // open master inerrupt switch
}

void loop() {

  char* datetime = getRTC();
  sendString(datetime);
  // sendString("hello world\n");
  P1_0 = !P1_0;
  delay(65535);
}

void sendByte(byte data) {
  SBUF = data;
  while (!TI)
    ;
  TI = 0;
}

void sendString(char *string) {
  while (*string) {
    sendByte(*string++);
  }
}

void delay(word i) {
  while (i--)
    ;
}

注:

1.15 I2C通信和EEPROM

I2C

AD和DA转换

LCD