[MCP79411通过Atmel SAMG55上的i2c / TWI接口进行RTC连接

问题描述 投票:0回答:1

我已经建立了一个基于ATSAMG55J19 MCU的项目,并使用Atmel Studio和ASF 3进行编程

现在,我正在尝试添加外部RTC时钟,因为内部SAMg55 rtc没有备用电池。该模块将用于在电源故障后读取当前时间,然后我将使用内部RTC,因此我只需要基本通信。无需将特定数据写入EEPROM或设置警报。

我有一个通过i2c连接的MCP79411,但是没有适合该使用ASF TWI库的MCU的库。

[有许多Arduino实现,但是它们使用Wire.h库,但我无法移植它。

我尝试移植此简单的“驱动程序”:https://www.ccsinfo.com/forum/viewtopic.php?t=54105

这里是一些代码

static void i2c_start(void){
    static twi_options_t ext3_twi_options;

    flexcom_enable(FLEXCOM4);
    flexcom_set_opmode(FLEXCOM4, FLEXCOM_TWI);

    ext3_twi_options.master_clk = sysclk_get_cpu_hz();
    ext3_twi_options.speed = 100000;
    ext3_twi_options.smbus = 0;

    twi_master_init(TWI4, &ext3_twi_options);
}

// Init Real Time Clock
void rtc_Init(void)
{
    uint8_t seconds = 0;

    i2c_start();
    twi_write_byte(TWI4, ADDR_RTCC_WRITE);     // WR to RTC
    twi_write_byte(TWI4, ADDR_SEC);                // REG 0

    twi_write_byte(TWI4, ADDR_RTCC_READ);      // RD from RTC
    seconds = bcd2bin(i2c_read(0)); // Read current "seconds" in rtc
    //i2c_stop();
    //seconds &= 0x7F;
    seconds |= 0x80; //set to 1 bit 7 of seconds(ST) enabling oscillator

    delay_us(3);

    twi_write_byte(TWI4, ADDR_RTCC_WRITE);      // WR to RTC
    twi_write_byte(TWI4, ADDR_SEC);      // REG 0
    twi_write_byte(TWI4, bin2bcd(seconds) | 0x80);     // Start oscillator with current "seconds value

    twi_write_byte(TWI4, ADDR_RTCC_WRITE);      // WR to RTC
    twi_write_byte(TWI4, 0x07);      // Control Register
    twi_write_byte(TWI4, 0x80);      // Disable squarewave output pin
    //i2c_stop();
}

然后我尝试了rtc_set_date_time(uint8_t日,uint8_t月,uint8_t年,uint8_t陶氏,uint8_t小时,uint8_t分钟,uint8_t秒)

void rtc_get_time(uint8_t &hr, uint8_t &min, uint8_t &sec)
{
    twi_write_byte(TWI4, ADDR_RTCC_WRITE);
    twi_write_byte(TWI4, 0x00);                     

    twi_write_byte(TWI4, ADDR_RTCC_READ);
    sec = bcd2bin(twi_read_byte(TWI4) & 0x7f);    //0x7f b01111111
    min = bcd2bin(twi_read_byte(TWI4) & 0x7f);    //0x7f
    hr  = bcd2bin(twi_read_byte(TWI4) & 0x3f);   //0x3f b00111111
    //i2c_stop();
}

但是我总是得到“ 0”字节。

i无法理解打开通信并从i2c读取字节的正确方法。

我发现的唯一参考是http://asf.atmel.com/docs/latest/sam.drivers.twi.twi_eeprom_example.samg53_xplained_pro/html/index.html,但它似乎是一种非常不同的通信类型。

通过i2c发送和接收字节的正确方法是什么?

i2c cortex-m microchip atmelstudio
1个回答
0
投票
#include "asf.h" #include "conf_board_3in4out.h" #include "external_rtc.h" #include <time.h> //#include <time_utils.h> twi_packet_t packet_tx, packet_rx; // helper functions to manipulate BCD and binary to integers static int bcd2dec(char r_char) { MSN = (r_char & 0xF0)/16; LSN = r_char & 0x0F; return(10*MSN + LSN); } static char msn(char tim) { return (tim & 0xF0)/16; } static char lsn(char tim) { return (tim & 0x0F); } #define RTC_ADDR 0x6F // 7 bits char config_t[10]; char config_2[8]; char tim_read[8]; #define ADDR_SEC 0x00 // address of SECONDS register #define ADDR_MIN 0x01 // address of MINUTES register #define ADDR_HOUR 0x02 // address of HOURS register #define ADDR_DAY 0x03 // address of DAY OF WEEK register #define ADDR_STAT 0x03 // address of STATUS register #define ADDR_DATE 0x04 // address of DATE register #define ADDR_MNTH 0x05 // address of MONTH register #define ADDR_YEAR 0x06 // address of YEAR register #define ADDR_CTRL 0x07 // address of CONTROL register #define ADDR_CAL 0x08 // address of CALIB register #define ADDR_ULID 0x09 // address of UNLOCK ID register #define ADDR_SAVtoBAT_MIN 0x18 // address of T_SAVER MIN(VDD->BAT) #define ADDR_SAVtoBAT_HR 0x19 // address of T_SAVER HR (VDD->BAT) #define ADDR_SAVtoBAT_DAT 0x1a // address of T_SAVER DAT(VDD->BAT) #define ADDR_SAVtoBAT_MTH 0x1b // address of T_SAVER MTH(VDD->BAT) #define START_32KHZ 0x80 // start crystal: ST = b7 (ADDR_SEC) #define OSCON 0x20 // state of the oscillator(running or not) #define VBATEN 0x08 // enable battery for back-up static uint8_t bin2bcd(uint8_t binary_value) { uint8_t temp; uint8_t retval; temp = binary_value; retval = 0; if(temp >= 10) { temp -= 10; retval += 0x10; } else { retval += temp; //break; } return(retval); } static uint8_t bcd2bin(uint8_t bcd_value) { uint8_t temp; temp = bcd_value; temp >>= 1; temp &= 0x78; return(temp + (temp >> 2) + (bcd_value & 0x0f)); } static void setConfig(void){ config_2[0] = tim_read[0] | START_32KHZ; // bitwise OR sets Start osc bit = 1 config_2[1] = tim_read[1]; config_2[2] = tim_read[2]; //0x03h – Contains the BCD day. The range is 1-7. //Bit 3 is the VBATEN bit. If this bit is set, the //internal circuitry is connected to the VBAT pin //when VCC fails. If this bit is ‘0’ then the VBAT pin is //disconnected and the only current drain on the //external battery is the VBAT pin leakage. config_2[3] = tim_read[3] | VBATEN; config_2[4] = tim_read[4]; config_2[5] = tim_read[5]; config_2[6] = tim_read[6]; config_2[7] = 0x00; // control b3 - extosc = 0 } static void initialize(void){ uint8_t buf[7]; // Fill this with RTC clock data for all seven registers // read stored time data config_t[0] = 0x00; //reset pointer reg to '00' // Set up config to read the time and set the control bits //i2c.write(addr, config_t, 1); // write address 00 packet_tx.chip = RTC_ADDR; packet_tx.addr[0] = 0; // RTCSEC packet_tx.addr_length = 1; packet_tx.buffer = config_t; packet_tx.length = 1; twi_master_write(TWI4, &packet_tx); delay_ms(250); // //i2c.read(addr, tim_read, 7); //read time ss mm hh from r1, r2, r3 packet_rx.chip = RTC_ADDR; packet_rx.addr[0] = 0; // RTCSEC packet_rx.addr_length = 1; packet_rx.buffer = tim_read; packet_rx.length = sizeof(tim_read); twi_master_read(TWI4, &packet_rx); delay_ms(250); setConfig(); //puts RTCC data into config array from tim_read array // write the config data //i2c.write(addr, config_t, 9); // write the config data back to the RTCC module packet_tx.chip = RTC_ADDR; packet_tx.addr[0] = 0; // RTCSEC packet_tx.addr_length = 1; packet_tx.buffer = config_2; packet_tx.length = sizeof(config_2); twi_master_write(TWI4, &packet_tx); } static void write_time(void){ // re-calculate mins mins = 8; //ORE 10:08 mins = mins%60; ch_mins = 16*(mins/10) + mins%10; MSN = msn(ch_mins); LSN = lsn(ch_mins); tim_read[1] = ch_mins; inc_mins = 0; //write the data back to RTCC setConfig(); //i2c.write(addr, config_t, 9); /* Configure the data packet to be transmitted */ packet_tx.chip = RTC_ADDR; packet_tx.addr[0] = 0; // RTCSEC packet_tx.addr_length = 1; packet_tx.buffer = config_2; packet_tx.length = sizeof(config_2); twi_master_write(TWI4, &packet_tx); //Display and set hours //hrs = bcd2dec(tim_read[2]); // re-calculate hrs hrs = 10; //ORE 10:08 hrs = hrs%24; ch_hrs = 16*(hrs/10) + hrs%10; MSN = msn(ch_hrs); LSN = lsn(ch_hrs); tim_read[2] = ch_hrs; inc_hr = 0; //write the data back to RTCC setConfig(); /* Configure the data packet to be transmitted */ packet_tx.chip = RTC_ADDR; packet_tx.addr[0] = 0; // RTCSEC packet_tx.addr_length = 1; packet_tx.buffer = config_2; packet_tx.length = sizeof(config_2); twi_master_write(TWI4, &packet_tx); } static void read_time(void){ //config_t[0] = 0x00; //reset pointer reg to '00' //// First Get the time ////i2c.write(addr, config_t, 1); // write address 00 //packet_tx.chip = RTC_ADDR; //packet_tx.addr[0] = 0; // RTCSEC //packet_tx.addr_length = 1; //packet_tx.buffer = config_t; //packet_tx.length = 1; // //twi_master_write(TWI4, &packet_tx); delay_ms(250); uint8_t buf[7]; // Fill this with RTC clock data for all seven registers /* Configure the data packet to be received */ packet_rx.chip = RTC_ADDR; packet_rx.addr[0] = 0; // RTCSEC packet_rx.addr_length = 1; packet_rx.buffer = buf; packet_rx.length = sizeof(buf); twi_master_read(TWI4, &packet_rx); for(uint8_t i = 0; i < sizeof(buf); i++){ tim_read[i] = buf[i]; } } void example_print_time(void){ //initialize(); delay_ms(1000); //write_time(); //commented to see if time is permanent delay_ms(1000); read_time(); while(1){ printf("Reading time\n"); printf("%d:%d:%d\n", bcd2dec(tim_read[2]), bcd2dec(tim_read[1]), bcd2dec(tim_read[0] ^ START_32KHZ)); delay_ms(1000); read_time(); } }
© www.soinside.com 2019 - 2024. All rights reserved.