PIC24FJ256GA108. I2C2. @#$%$#@!! @#$!!! @$#@$#@$!!! Устанавливает BCL в регистре статуса на первом start condition (который сам же и формирует). Если такое случилось (зависит от фазы луны и погоды на марсе, чаще не случается при первом включении питания) -- перестанет работать до длительного сброса или же длительного отключения питания (короткое -- не помогает). Зависит от наличия осциллографа и чёрт знает чего ещё. На microchip.com/forum много разного шаманства. Предлагаю свой метод лечения, если вкратце: вначале включить I2C2 модуль (в регистр I2C2CON), потом сделать софтрезет (старт, 9 клоков, стоп). А не наоборот. Помогает. Выделено цветным:
I2C2CON=0;
/* 400KHz rate, enable I2C */
I2C2STAT=0;
I2C2BRG=F_OSC/2/400000 - F_OSC/2/10000000 - 1;
I2C2CON=1<<15;
/* Bus reset -- start, 9 clocks, stop */
LATAbits.LATA15=0, LATAbits.LATA14=0;
TRISAbits.TRISA15=0; /* START (SDA=0) */
i2c_delay();
TRISAbits.TRISA14=0; /* SCL=0 */
i2c_delay();
TRISAbits.TRISA15=1; /* SDA=1 */
n=9; do {
i2c_delay();
TRISAbits.TRISA14=1; /* SCL=1 */
i2c_delay();
TRISAbits.TRISA14=0; /* SCL=0 */
} while(--n);
i2c_delay();
TRISAbits.TRISA15=0; /* STOP (SDA=0) */
i2c_delay();
TRISAbits.TRISA14=1; /* SCL=1 */
i2c_delay();
TRISAbits.TRISA15=1; /* SDA=1 */
i2c_delay();
i2c_fail=0;
i2c_start();
i2c_stop();
[ZX]
static int_fast8_t i2c_wait(void)
{
ftime_t t;
t=timer();
do {
if (I2C2STATbits.BCL) {
/* collision */
i2c_fail=I2C_FAIL_COLL;
return -1;
}
if ((I2C2CON & 0x1f)==0 && I2C2STATbits.TRSTAT==0)
/* finished ok */
return 0;
} while (timer() - t < (ftime_t)(10L*FTIME_PER_SEC/1000));
/* timeout! */
i2c_fail=I2C_FAIL_TO;
return -1;
}
static inline int_fast8_t i2c_start(void)
{
I2C2CONbits.SEN=1;
return i2c_wait();
}
static inline int_fast8_t i2c_stop(void)
{
I2C2CONbits.PEN=1;
return i2c_wait();
}
int i2c_init(void)
{
unsigned n;
TRISAbits.TRISA15=1, TRISAbits.TRISA14=1;
CNPU3bits.CN43PUE=1, CNPU3bits.CN44PUE=1;
КЛЮЧЕВОЙ МОМЕНТ:
if (!i2c_fail) return 0;
else return -1;
}
-
- Ё! И как быть с серийным изделием? - Make_Pic(04.10.2011 07:45)