24c32a EEPROM写操作在Attiny402上无法正常工作,我错了吗?

huangapple go评论66阅读模式
英文:

24c32a eeprom write operation not working with attiny402..am i mistaken?

问题

#define sda_on PORTA_DIRSET = PIN1_bm ; PORTA_OUTSET = PIN1_bm ;
#define sda_read PORTA_DIRCLR = PIN1_bm ;while(PORTA_IN & (PIN1_bm));PORTA_DIRSET = PIN1_bm ;
#define sda_off PORTA_DIRSET = PIN1_bm ;PORTA_OUTCLR = PIN1_bm ;
#define scl_on PORTA_DIRSET = PIN2_bm ;PORTA_OUTSET = PIN2_bm ;
#define scl_off PORTA_DIRSET = PIN2_bm ;PORTA_OUTCLR = PIN2_bm ;
#include <xc.h>
#include <util/delay.h>
void i2c_start(void)
{
    sda_on;
    scl_on;
    _delay_ms(10);
    sda_off;
    _delay_ms(10);
    scl_off;
}
void i2c_stop(void)
{
    sda_off;
    scl_off;
    _delay_ms(10);
    scl_on;
    _delay_ms(10);
    sda_on;
}
void i2c_data_write(unsigned char data)
{
    for(int i=0;i<8;i++)
    {
        if(data & 0x80) 
        {
            sda_on;
        }
        else sda_off;
        _delay_ms(10);
        scl_on;
        _delay_ms(10);
        scl_off;
        data = data << 1;
    }
    scl_on;
    sda_on;
    _delay_ms(10);
    sda_read;
    _delay_ms(10);   
    scl_off;
    _delay_ms(10);
}
英文:

#define sda_on PORTA_DIRSET = PIN1_bm ; PORTA_OUTSET = PIN1_bm ;
#define sda_read PORTA_DIRCLR = PIN1_bm ;while(PORTA_IN &amp; (PIN1_bm));PORTA_DIRSET = PIN1_bm ;
#define sda_off PORTA_DIRSET = PIN1_bm ;PORTA_OUTCLR = PIN1_bm ;
#define scl_on PORTA_DIRSET = PIN2_bm ;PORTA_OUTSET = PIN2_bm ;
#define scl_off PORTA_DIRSET = PIN2_bm ;PORTA_OUTCLR = PIN2_bm ;
#include &lt;xc.h&gt;
#include &lt;util/delay.h&gt;
void i2c_start(void)
{
    sda_on;
    scl_on;
    _delay_ms(10);
    sda_off;
    _delay_ms(10);
    scl_off;
}
void i2c_stop(void)
{
    sda_off;
    scl_off;
    _delay_ms(10);
    scl_on;
    _delay_ms(10);
    sda_on;
}
void i2c_data_write(unsigned char data)
{
    for(int i=0;i&lt;8;i++)
    {
        if(data &amp; 0x80) 
        {
            sda_on;
        }
        else sda_off;
        _delay_ms(10);
        scl_on;
        _delay_ms(10);
        scl_off;
        data = data &lt;&lt; 1;
    }
    scl_on;
    sda_on;
    _delay_ms(10);
    sda_read;
    _delay_ms(10);   
    scl_off;
    _delay_ms(10);
}

Its a just write operation in 24c32a eeprom using by Attiny402..its not working ..im using simulating with debugging by proteus software....i2c debugger gives always question mark while im run the simulation help me..

答案1

得分: 1

一个快速的答案:这些宏应该被改成使用按位或赋值|=和按位与赋值&=

#define sda_on PORTA_DIRSET |= PIN1_bm; PORTA_OUTSET |= PIN1_bm;
#define scl_on PORTA_DIRSET |= PIN2_bm; PORTA_OUTSET |= PIN2_bm;

sda_onPORTA_OUTSET设置为值PIN1_bm,而宏scl_onPORTA_OUTSET设置为值PIN2_bm

从这些宏中,我们知道sdascl这两个引脚都在PORTA上,并且这些宏使用了这两个引脚的位掩码。通常,端口引脚的位掩码只有一个位被设置,例如0x01或0x02或0x04等等。

然后,在i2c_start()函数的开头,一个sda_on后面跟着一个scl_on,这会使得PORTA的值设置为PIN2_bm而不是正确的值PIN1_bm | PIN2_bm,这样可以将两个引脚都设置为i2c起始条件的设置时间内的高电平。

void i2c_start(void)
{
  sda_on; // PORTA_DIRSET |= PIN1_bm; PORTA_OUTSET |= PIN1_bm;
  scl_on; // PORTA_DIRSET |= PIN2_bm; PORTA_OUTSET |= PIN2_bm;
  // 此时,PORTA_DIRSET |= PIN2_bm; PORTA_OUTSET |= PIN2_bm;
  // 但是不是PORTA_DIRSET |= PIN1_bm | PIN2_bm; PORTA_OUTSET |= PIN1_bm | PIN2_bm;
  _delay_ms(10);
  sda_off;
  _delay_ms(10);
  scl_off;
}

所以,粗略的解决方案是将宏修改为如下所示。

#define scl_on PORTA_DIRSET |= PIN2_bm; PORTA_OUTSET |= PIN2_bm;
#define scl_off PORTA_DIRSET &= ~PIN2_bm; PORTA_OUTCLR &= ~PIN2_bm;

或者,如果没有其他引脚与之共享同一个端口,你可以将两个引脚分别放在两个端口上,例如sda放在PORTA上,scl放在PORTB上,这样按位或赋值|=和按位与赋值&=将不是必要的。

英文:

a quick answer: those macros should be changed to use bit-wise-OR assignment |= and bit-wise-AND assignment &amp;= instead.

#define sda_on PORTA_DIRSET = PIN1_bm ; PORTA_OUTSET = PIN1_bm ;
#define scl_on PORTA_DIRSET = PIN2_bm ;PORTA_OUTSET = PIN2_bm ;

The macro sda_on sets PORTA_OUTSET to the value PIN1_bm, while the macro scl_on sets PORTA_OUTSET to the value PIN2_bm.

From those macros, we know the two pins sda and scl are both on PORTA, and the macros operate with bit-mask for the two pins. In general, a bit-mask of port pin would have only one bit set, like 0x01 or 0x02 or 0x04, and so on.

Then, at the beginning of i2c_start(), a sda_on is followed by a scl_on, that makes the value of PORTA set to PIN2_bm but not the correct value PIN1_bm | PIN2_bm which will set both pins to high level for the setup-time of a start-condition of i2c.

void i2c_start(void)
{
  sda_on; // PORTA_DIRSET = PIN1_bm ; PORTA_OUTSET = PIN1_bm ;
  scl_on; // PORTA_DIRSET = PIN2_bm ;PORTA_OUTSET = PIN2_bm ;
  // at this point, PORTA_DIRSET = PIN2_bm ;PORTA_OUTSET = PIN2_bm ;
  // But not, PORTA_DIRSET = PIN1_bm | PIN2_bm ;PORTA_OUTSET = PIN1_bm | PIN2_bm ;
  _delay_ms(10);
  sda_off;
  _delay_ms(10);
  scl_off;
}

So, the rough solution is to change the macros like the followings.

#define scl_on PORTA_DIRSET |= PIN2_bm ;PORTA_OUTSET |= PIN2_bm ;
#define scl_off PORTA_DIRSET &amp;= ~PIN2_bm ;PORTA_OUTCLR &amp;= ~PIN2_bm ;

Or, you could use two ports for the two pins, like sda on PORTA and scl on PORTB, if there is no other pin sharing the same port, then the bit-wise-OR assignment |= and bit-wise-AND assignment &amp;= would be not necessary.

huangapple
  • 本文由 发表于 2023年2月18日 13:30:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/75491404.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定