Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/video/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
通过Atmel SAMG55上的i2c/TWI接口进行MCP79411 RTC连接_I2c_Cortex M_Microchip_Atmelstudio - Fatal编程技术网

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

通过Atmel SAMG55上的i2c/TWI接口进行MCP79411 RTC连接,i2c,cortex-m,microchip,atmelstudio,I2c,Cortex M,Microchip,Atmelstudio,我做了一个基于ATSAMG55J19单片机的项目,用Atmel Studio和ASF 3编程 现在我尝试添加一个外部RTC时钟,因为内部SAMg55 RTC没有备用电池。 该模块将用于读取电源故障后的当前时间,然后我将使用内部RTC,所以我只需要基本的通信。无需在EEPROM中写入特定数据或设置报警 我有一个MCP79411,通过i2c连接,但是没有任何库适合使用ASF TWI库的MCU 有很多Arduino实现,但它们使用Wire.h库,我不能移植它 我尝试移植这个简单的“驱动程序”: 这里有

我做了一个基于ATSAMG55J19单片机的项目,用Atmel Studio和ASF 3编程

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

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

有很多Arduino实现,但它们使用Wire.h库,我不能移植它

我尝试移植这个简单的“驱动程序”:

这里有一些代码

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设置日期时间(uint8天、uint8月、uint8年、uint8道指、uint8小时、uint8分钟、uint8秒)

但我总是得到“0”字节

我无法理解打开通信和从i2c读取字节的正确方法

我找到的唯一参考资料是,但它似乎是一种非常不同的交流方式


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

我设法获取和设置了数据。我张贴了一份图书馆的草稿:

#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();
    }
}
#包括“asf.h”
#包括“conf_board_3in4out.h”
#包括“外部_rtc.h”
#包括
//#包括
两个数据包发送,数据包接收;
//用于将BCD和二进制操作为整数的辅助函数
静态整数bcd2dec(字符r\u字符)
{
MSN=(r_char&0xF0)/16;
LSN=r_字符&0x0F;
返回(10*MSN+LSN);
}
静态字符msn(字符tim)
{
返回(tim&0xF0)/16;
}
静态字符lsn(字符tim)
{
返回(tim&0x0F);
}
#定义RTC_ADDR 0x6F//7位
字符配置[10];
字符配置_2[8];
char tim_read[8];
#定义ADDR_SEC 0x00//秒寄存器的地址
#定义ADDR_MIN 0x01//分钟寄存器的地址
#定义ADDR_HOUR 0x02//小时寄存器的地址
#定义地址0x03//星期几寄存器的地址
#定义ADDR_STAT 0x03//状态寄存器的地址
#定义地址日期0x04//日期寄存器的地址
#定义地址0x05//月份寄存器的地址
#定义地址年份0x06//年份寄存器地址
#定义ADDR\u CTRL 0x07//控制寄存器的地址
#定义地址CAL 0x08//CALIB寄存器的地址
#定义地址ULID 0x09//解锁ID寄存器的地址
#定义地址SAVtoBAT\u MIN 0x18//地址savt\u MIN(VDD->BAT)
#定义ADDR_SAVtoBAT_HR 0x19//T_SAVER HR的地址(VDD->BAT)
#定义ADDR_SAVtoBAT_DAT 0x1a//T_SAVtoBAT DAT的地址(VDD->BAT)
#定义ADDR_SAVtoBAT_MTH 0x1b//T_SAVER MTH的地址(VDD->BAT)
#定义起始频率32KHZ 0x80//起始晶体:ST=b7(地址秒)
#定义振荡器的OSCON 0x20//状态(运行或不运行)
#定义VBATEN 0x08//启用备用电池
静态uint8_t二进制值2BCD(uint8_t二进制值)
{
uint8温度;
uint8_t retval;
温度=二进制值;
retval=0;
如果(温度>=10)
{
温度-=10;
retval+=0x10;
}
其他的
{
retval+=温度;
//中断;
}
返回(retval);
}
静态uint8\u t bcd2bin(uint8\u t bcd\u值)
{
uint8温度;
温度=bcd_值;
温度>>=1;
温度&=0x78;
返回(temp+(temp>>2)+(bcd_值&0x0f));
}
静态void setConfig(void){
config_2[0]=tim_read[0]| START_32KHZ;//按位或设置START osc bit=1
config_2[1]=tim_read[1];
config_2[2]=tim_read[2];
//0x03h–包含BCD日。范围为1-7。
//位3是VBATEN位。如果设置了此位,则
//内部电路连接到VBAT引脚
//当VCC失败时。如果此位为“0”,则VBAT引脚为
//已断开,并且是上唯一的电流消耗
//外部电池是VBAT引脚泄漏。
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;//控件b3-extosc=0
}
静态void初始化(void){
uint8_t buf[7];//用这七个寄存器的RTC时钟数据填充
//读取存储的时间数据
config_t[0]=0x00;//将指针注册表重置为“00”
//设置配置以读取时间并设置控制位
//i2c.write(地址,配置,1);//写入地址00
packet_tx.chip=RTC_ADDR;
数据包_tx.addr[0]=0;//RTCSEC
数据包发送地址长度=1;
数据包\u tx.buffer=config\u t;
数据包发送长度=1;
twi\u主机写入(TWI4和数据包发送);
延迟时间(250);
//
//i2c.read(addr,tim_read,7);//从r1、r2、r3读取时间ss mm hh
packet_rx.chip=RTC_ADDR;
数据包_rx.addr[0]=0;//RTCSEC
数据包接收地址长度=1;
数据包接收缓冲区=tim读取;
数据包接收长度=sizeof(tim读取);
两次主控读取(两次4和数据包接收);
延迟时间(250);
setConfig();//将RTCC数据从tim_读取数组放入配置数组
//写入配置数据
//i2c.write(addr,config_t,9);//将配置数据写回RTCC模块
packet_tx.chip=RTC_ADDR;
数据包_tx.addr[0]=0;//RTCSEC
数据包发送地址长度=1;
数据包_tx.buffer=config_2;
数据包长度=sizeof(配置2);
twi\u主机写入(TWI4和数据包发送);
}
静态无效写入时间(无效){
//重新计算分钟
分钟=8;//或10:08
分钟=分钟%60;
Chu_mins=16*(分钟/10)+分钟%10;
MSN=MSN(每分钟);
LSN=LSN(每分钟);
tim_read[1]=Chu mins;
inc_mins=0;
//将数据写回RTCC
setConfig();
//i2c.write(地址,配置,9);
/*配置要传输的数据包*/
帕
#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();
    }
}