MicroCHIP.RU
Главная Документация Отладочные средства Справочник Поиск Ссылки
 Новости   Конференция   Контакты 
 

Re:СМОТРИ!!! Выкладываю I2C master который исполь

 Нoвaя темa  |  Наверх  |  Перейти к теме  |  Поиск  |  Правила  |  Вход 

ВНИМАНИЕ!
Вы просматриваете архив форума.

Этот форум работает только в режиме просмотра и поиска.

Действующий форум переведен на новый движок и
находится по адресу www.microchip.su

 HELP!!! Slave аппаратный на P16F87x
Автор: Алексей ()
Дата:   12/03/2002 19:16

Устал бороться:
1. Принимаю адрес
2. ПРинимаю первый байт
3. А потом все...
4. Программа обработки из AN734 - работа по прерывания и контролю SSPSTAT/
5. Уменьшил частоту посылки с 400 кГц до 100 кГц - ну чуть лучше.
6. Изменение к апноту внес:

ReadI2C
banksel SSPCON,SSPOV
btfsc SSPCON,SSPOV
bcf SSPCON,SSPOV

banksel SSPBUF
movf SSPBUF,w
return

Данные из W потом записываются в приемный буфер.

7. Проверка при выходе из прерывания внес проверку:

call SSP_Handler ; Это обработчик из апнота.

; Дабавил проверку SSPSTAT на наличие данных в буфере

banksel SSPBUF
btfsc SSPBUF,BF
goto $-4

Ситуация чуть улучшилась но сбоит страшно.

УСТАЛ!!! Если у кого есть кусок готовой проги, ПОЖАЛУЙСТА - не поскупитесь.

С УВАЖЕНИЕМ К НАРОДУ,
Алексей.


 
 Re: I2C slave аппаратный на P16F87x
Автор: DRcp ()
Дата:   13/03/2002 10:07

Программа в поле пока не работала но на столе ведёт себя вроде номально.
Принцип обмена:
ожидание записи в буфер (условия: мой адрес и STOP),
обработка буфера,
если нужен ответ, то он кладётся в буфер.

CODE
SSPSTAT_WORK equ (0 << SMP) + (0 << CKE) + (0 << D_A) + (0 << P) + (0 <<
S) + (0 << R_W) + (0 << UA) + (0 << BF)
SSPCON_WORK equ (0 << WCOL) + (0 << SSPOV) + (1 << SSPEN) + (1 << CKP)
+ (0 << SSPM3) + (1 << SSPM2) + (1 << SSPM1) + (0 << SSPM0)
SSPCON2_WORK equ (0 << GCEN) + (0 << ACKSTAT) + (0 << ACKDT) + (0 <<
ACKEN) + (0 << RCEN) + (0 << PEN) + (0 << RSEN) + (0 << SEN)
SSPADD_WORK equ 0x30 ; I2C Адрес



cblock 0x20
pushst ; копия STATUS при обработке прерываний
pushpch ; копия PCLATH при обработке прерываний

I2C_index ; указатель в буфере I2C

i2cbuf0 ; буфер I2C
i2cbuf1
i2cbuf2
i2cbuf3
i2cbuf4
i2cbuf5
i2cbuf6
i2cbuf7
i2cbuf8
i2cbuf9

FSR_TMP ; копия FSR при обработке прерываний
endc

cblock 0x71
pushw ; копия W при обработке прерываний
endc












start: org 0
pagesel main_init
goto main_init



;обработка прерываний
int: org 4
movwf pushw
swapf STATUS,W
clrf STATUS
movwf pushst
movf PCLATH,W
movwf pushpch
clrf PCLATH



btfsc PIR1,SSPIF ; прерывание от SSP ?
goto SSP ; переход на обработку прерывания от SSP
no_SSP:


bcf PIR2,BCLIF ; сбросить флаг запроса от неиспользуемого
прерывания

movf pushpch,W
movwf PCLATH
swapf pushst,W
movwf STATUS
swapf pushw,F
swapf pushw,W
retfie












SSP:
;;;;;;; bcf SSPCON,CKP ; ТОЛЬКО ДЛЯ ОТЛАДКИ ! Она удерживает SCL и
нарушает STOP-последовательность!

bcf PIR1,SSPIF ; сбросить запрос на прерывание от SSP

bsf STATUS,RP0 ; RAM bank 1

movf SSPSTAT,W ; скопировать биты R_W и BF
andlw (1 << R_W) + (1 << BF)
movwf PCLATH ; PCLATH используется для временного хранения
битов R_W и BF

btfss SSPSTAT,D_A ; адрес или данные ?
goto D_A__ADRES
D_A__DATA:
bcf STATUS,RP0 ; RAM bank 0

D_A__0__R_W__1:
movf FSR,W ; сохранить значение FSR
movwf FSR_TMP

bcf STATUS,IRP ; установить IRP

movf I2C_index,W ; настроить косвенную адресацию на буфер I2C
andlw 0x0f
addlw low i2cbuf0
movwf FSR

btfsc PCLATH,R_W ; чтение или запись ?
goto R_W__READ
R_W__WRITE:
btfss PCLATH,BF ; перегрузить данные только если BF = 1
goto R_W_end
movf SSPBUF,W ; сохранить данные в буфере
movwf INDF
goto R_W_end
R_W__READ:
movf INDF,W ; передать данные из буфера
movwf SSPBUF
R_W_end:
incf I2C_index,W ; проверить указатель на выход за пределы буфера
andlw 0x0f
sublw 9
btfsc STATUS,C
incf I2C_index,F ; передвинуть указатель

movf FSR_TMP,W ; восстановить значение FSR
movwf FSR

SSP_end:
bcf SSPCON,WCOL ; сбросить возможные ошибки
bcf SSPCON,SSPOV
bsf SSPCON,CKP ; отпустить SCL после чтения
goto no_SSP



D_A__ADRES:
bcf STATUS,RP0 ; RAM bank 0
movf SSPBUF,W ; прочитать SSPBUF для обнуления BF
clrf I2C_index ; установить указатель на начало буфера
btfsc PCLATH,R_W
goto D_A__0__R_W__1 ; чтение
bsf I2C_index,7 ; установить бит об обращении ко мне (только
если запись)
goto SSP_end ; запись













; Обработка запроса по I2C
I2C_paket:
banksel PIR1 ; RAM bank 0
bcf SSPCON,SSPEN ; сбросить бит P выключением SSP
bsf SSPCON,SSPEN
clrf I2C_index ; сбросить бит об обращении ко мне

; Здесь обработка строки записанной в i2cbuf0-i2cbuf9

return












main:
clrwdt ; сбросить WDT

banksel PIR1 ; RAM bank 0
btfss I2C_index,7 ; Есть мой адрес ?
goto no_I2C_paket
bsf STATUS,RP0 ; RAM bank 1
btfss SSPSTAT,P ; Есть STOP бит ?
goto no_I2C_paket
clrf PCLATH ; Program memory bank 0
pagesel I2C_paket
goto I2C_paket ; обработать запрос по I2C
no_I2C_paket:

goto main












main_init:

;
;
;

; Настройка TRISC и PORTC

; Настройка SSP
banksel PIR1 ; RAM bank 0
movlw SSPCON_WORK ; настроить SSPCON
movwf SSPCON
bsf STATUS,RP0 ; RAM bank 1
movlw SSPCON2_WORK ; настроить SSPCON2
movwf SSPCON2
movlw SSPADD_WORK ; настроить SSPADD
movwf SSPADD
movlw SSPSTAT_WORK ; настроить SSPSTAT
movwf SSPSTAT
bsf PIE1,SSPIE ; разрешить прерывание от SSP
bcf STATUS,RP0 ; RAM bank 0

clrf I2C_index ; настроить указатель в буфере I2C

;
;
;

pagesel main
goto main



end
/CODE


 
 Re: I2C slave аппаратный на P16F87x
Автор: Petr ()
Дата:   13/03/2002 15:38

Вот пример прерывания на С.

static void
interrupt
/*прерывание I2C*/
prer(void)
{
unsigned char prom; /*просто переменная*/

if(STAT_RW == 0) /*происходит прием
данных*/
if(STAT_DA == 0) prom=SSPBUF; /*принят адрес и освобождаем
буфер*/
else /*приняты данные*/
{
prom=SSPBUF; /*обработка данных*/
/*тут надо обрабатывать данные*/

obrabotka(); /*работа с шлейфами*/
}
else /*происходит
передача данных*/
{
/*в sost_dat должны лежать данные для передачи*/

SSPBUF=sost_dat; /*данные для передачи в буфер*/
CKP=1; /*запустили передачу освободив SCL*/
SSPIF=0; /*сброс флага прерывания*/
while(SSPIF == 0);
}
SSPIF=0; /*сброс флага прерывания*/
}


 
 Re: I2C slave аппаратный на P16F87x
Автор: Алексей ()
Дата:   14/03/2002 18:30

Спасибо за ответ.
Но тестирование показало, что падает STOP/
Более подробно:
-посылка выглядит так: Start, Adres, Dtata1, Data2, Stop. Просто для
тестировнаия.
-в процесе обмена произвожу визуальный контроль состояния системы:
-контролирую прием по количеству посылок (при вхождении в Адрес)
-контролирую количество принятых байтов (при обработке посылки)
-контролирую состояние битов SSPSTAT.

Что происходит:
-количество нормальных обменов нельзя предсазать, т.е. система виснет не
предсказуемо.
-при состоянии когда индицируется, что принятых байтов =1, следующий байт
теряется и состояние флагов становиться: Start + Информационный байт.

Вывод (может я и не прав):
При приеме второго байта пакета мастер теряет ACK, затем slave теряет
stop и происходить то, что происходит.

Ребята устал бороться со SLAVE. Виснет гад и теряет байты.

С уважением, Алексей.


 
 Re: I2C slave аппаратный на P16F87x
Автор: DRcp ()
Дата:   15/03/2002 09:03

Лучше выложи все фрагменты которые относятся к slave I2C, кстати а в качестве
мастера что? Или программу(ы) целиком кинь на мыло (без know haw).


 
 А все ли хорошо у мастера ??
Автор: ALHO ()
Дата:   15/03/2002 10:09

Может он кривенький ???????


 
 Re: I2C slave аппаратный на P16F87x
Автор: Petr ()
Дата:   15/03/2002 13:22

Кстати тот мой пример слейва гарантированно работает
с моим примером мастера.
А мой мастер работает с памятью и RTC и микросхемами цветности
и ФАПЧами.Так что видимо он правильный.
Кстати у меня проблемы были именно с подтверждениями.
Внимательно посмотри выставление ответов и моменты
выставления бита прерывания.


 
 Re: I2C slave аппаратный на P16F87x
Автор: Алексей ()
Дата:   15/03/2002 13:42

Спасибо за ответы.
Мой Мастер то же работает с памятью и часами и не разу не сбойнул.
Сегодня чуть позже выложу мастера и slave 2-варианта.
Еще раз спасибо.

Алексей.


 
 Re:СМОТРИ!!! Выкладываю I2C master который исполь
Автор: Алексей ()
Дата:   15/03/2002 20:10

;---------------------------------------------------------------------
; Include Files
;---------------------------------------------------------------------

list p=16f873 ; list directive to define processor
#include <p16f873.inc> ; processor specific variable definitions

__CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON & _XT_OSC &
_WRT_ENABLE_OFF & _LVP_OFF & _CPD_OFF


; ************************************************************************
; КОНСТАНТЫ АВТОМАТА
; ************************************************************************
;---------------------------------------------------------------------
; Константы
;---------------------------------------------------------------------

#define FOSC D'4000000' ; Наша тактовая частота 4.0 MGz.
#define I2CClock D'100000' ; Скорость обмена по I2C 100 kGz.
#define ClockValue (((FOSC/I2CClock)/4) -1) ; Значение SSPADD для загрузки в
BRG.


Adr1307 equ b'11010000' ; I2C-адрес микросхемы DS1307
(RealTimeClock) ADR $A2
Adr24C01 equ b'10100000' ; I2C-адрес микросхемы AT24C01
AdrMG210 equ b'01110000' ; I2C-адрес
микросхемы MG210 (0x70)

; ************************************************************************
; ФЛАГИ АВТОМАТА
; ************************************************************************

#define ack_error 0 ; I2C флаг
ошибки.

;---------------------------------------------------------------------
; Описание переменных модуля
;---------------------------------------------------------------------

org 0x20

; +-----------------------------------------+
; Переменные для хранения состояния
; микроконтроллера при входе в прерывание.
; +-----------------------------------------+
WREGsave equ 0x20 ;
Переменная для хранения значения регистра W.
STATUSsave equ 0x21 ;
Переменная для хранения значения регистра STATUS.
FSRsave equ 0x22 ;
Переменная для хранения значения регистра FSR.
PCLATHsave equ 0x23 ;
Переменная для хранения значения регистра PCLTH.

eflag_event equ 0x24 ;
temp equ 0x25 ;
DelayCtr1 equ 0x26
DelayCtr2 equ 0x27

EE_ADDR equ 0x28
EE_DATA equ 0x29

cntra equ 0x2A
cntrb equ 0x2B

;---------------------------------------------------------------------
; Векторы
;---------------------------------------------------------------------

org 0x00
Reset
goto Startup ;
Инициализация микроконтроллера.

;*********************************************************************
; INTERRUPT'S SERVICE
;*********************************************************************

ISR
org 0x04

;---------------------------------------------------
; Сохраним значение регистров программы
;---------------------------------------------------

PUSH
movwf WREGsave ;
Сохраним текущее значение регистра W.
swapf STATUS,W ;
Получим текущее значение регистра STATUS.
clrf STATUS ;
Сбросим регистр STATUS, адресация к первой станице.
movwf STATUSsave ;
Сохраним значение регистра STATUS.
movf PCLATH,W ;
Получим текущее значение регистра PCLATH.
movwf PCLATHsave ;
Сохраним значение регистра PCLATH.
movf FSR,W ;
Получим текущее значение регистра FSR.
movwf FSRsave ;
Сохраним значение регистра FSR.

clrf PCLATH ;
Установим первый банк памяти программ.


;---------------------------------------------------
; Восстановим значение регистров программы
;---------------------------------------------------

POP
banksel FSRsave ; Выбор
банка памяти хранения переменных.
movf FSRsave,W ;
Получить старое значение FSR.
movwf FSR
; Восстановим значение FSR.
movf PCLATHsave,W ; Получим
старое значение PCLATH.
movwf PCLATH ;
Восстановим значение PCLATH.
movf STATUSsave,W ; Получим
старое значение STATUS.
movwf STATUS ;
Восстановим значение STATUS.
swapf WREGsave,F ;
Полуим старое значение W.
swapf WREGsave,W ;
Восстановим значение регистра W.

retfie
; Возврат из прерывания.

;---------------------------------------------------------------------
; ОСНОВНОЙ КОД ПРОГРАММЫ
;---------------------------------------------------------------------

Startup
bcf STATUS,RP1
; Выбираем первую страницу
bsf STATUS,RP0
; памяти переменных программы.
call Setup ; Вызов
подпрограммы инициализации контроллера.

; -------------------------------
; Очистка первого банка памяти
; -------------------------------

movlw 0x20 ;
Очистка памяти 0х20 - 0х7F
movwf FSR
; Загрузить адрес в регистр косвенной адресации
ClrMem0 clrf INDF ; Очистить
ячейку по адресу INDF
incf FSR,F ;
Увеличить значение адреса на еденицу
btfss FSR,7 ;
Достигли конца памяти ланных?
goto ClrMem0 ; Нет,
продолжим очистку.

; -------------------------------
; Очистка второго банка памяти
; -------------------------------

movlw 0xA0 ;
Очистка памяти 0хA0 - 0хFF
movwf FSR
; Загрузить адрес в регистр косвенной адресации
ClrMem1 clrf INDF ; Очистить
ячейку по адресу INDF
incf FSR,F ;
Увеличить значение адреса на еденицу
btfss STATUS,Z ;
Достигли конца памяти ланных?
goto ClrMem1 ; Нет,
продолжим очистку.

;--------------------------------
;--------------------------------

Main
call I2CStart ; Вдыем
импульс "Start".
btfsc STATUS,C ;
Проверим может линия занята?
goto $-2
; Да, линия занята повторим попытку.

movlw AdrMG210 ; Адоес
slave-устройства.
call I2CTransW ;
Передаем адрес устройства.
bnz Stop
; Если не получено подтверждение (ACK) прекратим посылку.

movlw b'00000011' ;
Первый байт посылки.
call I2CTransW ;
Передаем первй байт.
bnz $-3
; Если slave не подтвердил прием, повторим передачу.

movlw b'00000110' ;
Второй байт посылки.
call I2CTransW ;
Передаем второй байт.
bnz $-3
; Если slave не подтвердил прием, повторим передачу.
Stop
call I2CStop ; Выдем
импульс "Stop".

call hlfsec ;
Задержка примерно 1 сек.
goto Main ;
Повторим передачу пакета.


;*********************************************************************
; SETUP SERVICE
;*********************************************************************
;---------------------------------------------------------------------
; Начальная инициализация переменных программы и регистров работы
; с переферийным оборудованием.
;---------------------------------------------------------------------

Setup
banksel INTCON ;
Выбираем банк памяти хранения регистра INTCON.
clrf INTCON ;
Сбросим все флаги прерываний.

banksel PCON ;
Выбираем банк памяти хранения регистра PCON.
bsf PCON,NOT_POR ;
Установим флаг сброс по включению питания.
bsf PCON,NOT_BOR ;
Установим флаг сброс по снижению напряжения.

banksel PIR1 ;
Выбираем банк памяти хранения регистра PIR1.
clrf PIR1 ;
Сбросим флаги работы с переферийными устройствами.



;--------------------------------------------------------------
; Настройка портов ввода-вывода

;--------------------------------------------------------------

clrf PORTA ;
Очистка порта PORTA.
clrf PORTB ;
Очистка порта PORTB.
clrf PORTC ;
Очистка порта PORTC.

; PORTA 76543210
; ??????
; ?????+- RA<0> --
; ????+-- RA<1> --
; ???+--- RA<2> --
; ??+---- RA<3> --
; ?+----- RA<4> --
; +------ RA<5> --

; PORTB 76543210
; ||??????
; ||?????+- RB<0> --
; ||????+-- RB<1> --
; ||???+--- RB<2> --
; ||??+---- RB<3> --
; ||?+----- RB<4> --
; ||+------ RB<5> --
; |+------- RB<6> --
; +-------- RB<7> --

; PORTC 76543210
; ????????
; ???????+- RC<0> --
; ??????+-- RC<1> --
; ?????+--- RC<2> --
; ????+---- RC<3> SCL I2C линия тактирования данных.
; ???+----- RC<4> SDA I2C линия данных.
; ??+------ RC<5> --
; ?+------- RC<6> --
; +-------- RC<7> --

movlw b'00011000' ; Маска
для выводов порта PORTC.
banksel TRISA ; Выбор
банка памяти хранения регистров TRISx
clrf TRISA ; Все
выводы порта PORTA как выход.
clrf TRISB ; Все
выводы порта PORTB как выход.
movwf TRISC ;
Настройка портов линий I2C как ввод.


;--------------------------------------------------------------
; Инициализация модуля SSP

;--------------------------------------------------------------
; Для операций I2C модуль SSP имеет пять регистров:
; SSPCON - регистр управления
; SSPSTAT - регистр состояния
; SSPADD - скорость обмена = Fosc/(4x(SSPADD+1))
; SSPBUF - буфер приемника/передатчика
; SSPSR - сдвиговый регистр (не доступен для
программы)

;--------------------------------------------------------------

call init_i2c ;

; -------------------------------
; Настройка предделителя таймера
; -------------------------------
MOVLW B'10000001' ; Маска ...
; ????????
; ???????+- PS0 предварительный делитель для WDT или TMR0
; ??????+-- PS1 1:4
; ?????+--- PS2
; ????+---- PSA 1 - предварительный делитель для
WDT, иначе для TMR0
; ???+----- T0SE 1 - внешнее тактирование по спаду,
иначе по нарастанию
; ??+------ T0CS 1 - тактирование по внешнему входу,
иначе по частоте Fosc/4
; ?+------- INTEDG 1 - прерывание по нарастанию на RB0,
иначе по спаду
; +-------- RBPU 1 - запрещение подтягивающих резисторов
на RB

banksel OPTION_REG ;
MOVWF OPTION_REG ; Утановка
таймера TMR0 с преддеоителем на 1:4


;--------------------------------------------------------------
; Инициализация прерыаний микроконтроллера

;--------------------------------------------------------------
;

;--------------------------------------------------------------

; banksel INTCON ;
; bsf INTCON,T0IE
; Разрешим прерывания от таймера TMR0.
; bsf INTCON,GIE
; Установим флаг глобального разрешения прерываний.

bcf STATUS,RP0
; Выбор банка памяти 0.
return
; Возврат из подпрограммы инициализации контроллера.

;----------------------------------------------------------------------
; ******************* Инициализация модуля MSSP *******************
;----------------------------------------------------------------------

init_i2c
banksel SSPADD ; Выбираем банк памяти регистра
SSPADD.
movlw ClockValue ; Получим значение выбранной
частоты.
movwf SSPADD ; Инициализируем частоту обмена
I2C.
bcf SSPSTAT,CKE ; Установим выходные уровни в
соответствии с I2C.
bsf SSPSTAT,SMP ; Выбираем медленную скорость
обмена (100 kGz).

movlw b'00111000' ; Маска настройки модуля MSSP.
banksel SSPCON ; Выбираем банк памяти регистра
SSPADD.
movwf SSPCON ; Выбираем режим "мастер",
модуль SSP включен.
return ; Возврат из подпрограммы.

;-----------------------------------------------------------------------
; Генерирование на шине I2C импульса "start"
;-----------------------------------------------------------------------

I2CStart ;
Посылка импульса "СТАРТ"
banksel PIR1 ; Выбираем банк
хранения регистра PIR1.
bcf PIR1,SSPIF ;
Гарантированно сбросим бит флага прерывания.

bsf STATUS,C ;
Установим флаг переноса в регистре STATUS.

btfss PORTC,3 ; SCL-занята?
return ; Да,
на выход.
btfss PORTC,4 ; SDA-занята?
return ; Да,
на выход.

banksel SSPCON2 ; Выбираем банк хранения
регистра SSPCON2.
bsf SSPCON2,SEN ; Инициализируем START,
установкой бита SEN в регистре SSPCON2.
btfsc SSPCON2,SEN ; SEN снят?
goto $-1 ; Нет,
ожидаем пока железо его не уронит.
banksel PIR1 ; Выбираем банк
хранения регистра PIR1.
bcf PIR1,SSPIF ;
Сбросим флаг прерывания.

; Стартовый импульс прошел нормально. Сбросим флаг ошибки и
возвращаемся.

bcf STATUS,C ;
Очистим флаг переноса в регистре STATUS.
return ; Возврат из подпрограммы.

;-----------------------------------------------------------------------
; Генерирование на шине I2C импульса "stop" условия посылки
;-----------------------------------------------------------------------

I2CStop
banksel PIR1 ; Выбираем банк
памяти регистра PIR1.
bcf PIR1,SSPIF ;
Сбросим флаг прерывания.

banksel SSPCON2 ; Выбор банка памяти регистра
SSPCON2.
bsf SSPCON2,PEN ; Инициируем STOP, установкой
бита PEN в регистре SSPCON2.
btfsc SSPCON2,PEN ; Ожидаем
окончания стоп последовательности.
goto $-1 ; Еще
не закончено.
banksel PIR1 ; Выбираем банк
хранения регистра PIR1.
bcf PIR1,SSPIF ;
Сбросим флаг прерывания.
return ; Возврат из подпрограммы.

;-----------------------------------------------------------------------
; Передача байта приемнику по I2C
;-----------------------------------------------------------------------

I2CTransW
banksel PIR1 ; Выбираем банк
памяти регистра PIR1.
bcf PIR1,SSPIF ;
Сбросим флаг прерывания.

banksel SSPBUF ; Выбираем банк памяти хранения
регистра SSPBUF.
movwf SSPBUF ; Инициализируем передачу
очередного байта из W по шине I2C.

banksel PIR1 ; Выбираем банк
памяти регистра PIR1.
btfss PIR1,SSPIF ; Ожидаем
установки бита SSPIF после команды START.
goto $-1 ; Бит
пока не установлен.
bcf PIR1,SSPIF ;
Ожидаем установки бита SSPIF после окончания посылки байта.

banksel SSPCON2 ; Выбор банка хранения регистра
SSPCON2.
bsf STATUS,Z ;
Установим флаг ошибки приема - бит Zero в регистре STATUS.
btfsc SSPCON2,ACKSTAT ; Проверка бита подтверждения
от slave.
bcf STATUS,Z ;
Подтверждение получено, снимаем флаг ошибки приема байта.

banksel PIR1 ; Выбираем банк
хранения регистра PIR1.
bcf PIR1,SSPIF ;
Сбросим флаг прерывания.
return ; Да, подтверждение
получено, выход из подпрограммы.

;----------------------------------------------------------------------
; Чтение данных от slave по I2C c выдачей ACK
;----------------------------------------------------------------------

I2CReciveA
banksel SSPCON2 ; Выбираем банк памяти регистра
SSPCON2.
bsf SSPCON2,RCEN ; Разрешим прием данных
с шины I2C.

banksel PIR1 ; Выбираем банк
памяти регистра PIR1.
btfss PIR1,SSPIF ; Ожидаем
установки бита SSPIF после команды Recive.
goto $-1 ; Бит
пока не установлен, SSP еще не принял данные.

call SendAck ; Даем
подтверждение.

banksel SSPBUF ; Выбираем банк памяти регистра
SSPBUF.
movf SSPBUF,w ; Получим байт с шины I2C в
регистр W.

banksel PIR1 ; Выбираем банк
памяти регистра PIR1.
bcf PIR1,SSPIF ;
Ожидаем установки бита SSPIF после команды Recive.
return ; Возврат из подпрограммы.

;----------------------------------------------------------------------
; Чтение данных от slave по I2C c без выдачи ACK
;----------------------------------------------------------------------

I2CRecive
banksel SSPCON2 ; Выбираем банк памяти регистра
SSPCON2.
bsf SSPCON2,RCEN ; Разрешим прием данных
с шины I2C.

banksel PIR1 ; Выбираем банк
памяти регистра PIR1.
btfss PIR1,SSPIF ; Ожидаем
установки бита SSPIF после команды Recive.
goto $-1 ; Бит
пока не установлен, SSP еще не принял данные.

call SendNack ; Выдаем NACK.

banksel SSPBUF ; Выбираем банк памяти регистра
SSPBUF.
movf SSPBUF,w ; Получим байт с шины I2C в
регистр W.

banksel PIR1 ; Выбираем банк
памяти регистра PIR1.
bcf PIR1,SSPIF ;
Ожидаем установки бита SSPIF после команды Recive.
return ; Возврат из подпрограммы.

;----------------------------------------------------------------------
; Send Not Acknowledge
;----------------------------------------------------------------------
SendNack
banksel SSPCON2 ; select SFR bank
bsf SSPCON2,ACKDT ; acknowledge bit state to send
(not ack)
bsf SSPCON2,ACKEN ; initiate acknowledge sequence

banksel PIR1 ; Выбираем банк
памяти регистра PIR1.
btfss PIR1,SSPIF ; Ожидаем
установки бита SSPIF после команды START.
goto $-1 ; Бит
пока не установлен.
bcf PIR1,SSPIF ;
return ; Возврат из подпрограммы.

;----------------------------------------------------------------------
; Send Acknowledge
;----------------------------------------------------------------------

SendAck
banksel SSPCON2 ; select SFR bank
bcf SSPCON2,ACKDT ; acknowledge bit state to send
bsf SSPCON2,ACKEN ; initiate acknowledge sequence
btfsc SSPCON2,ACKEN ; ack cycle complete?
goto $-1 ; no, so loop again

banksel PIR1 ; Выбираем банк
памяти регистра PIR1.
btfss PIR1,SSPIF ; Ожидаем
установки бита SSPIF после команды START.
goto $-1 ; Бит
пока не установлен.
bcf PIR1,SSPIF ;
return ; Возврат из подпрограммы.


; ***************************************
; * FULL *
; ***************************************

full
movlw d'3' ;
movwf cntrb ;
vdly0
movlw d'43' ;
movwf cntra ;
vdly1
decfsz cntra,f ;
goto vdly1 ;
decfsz cntrb,f ;
goto vdly0 ;
retlw 0

; ***************************************
; * HLFSEC *
; ***************************************

hlfsec
banksel DelayCtr1 ;
movlw 0x05 ;
movwf DelayCtr1 ;
hlfsec1
clrf DelayCtr2 ;
hlfsec2
call full ;
decfsz DelayCtr2,f ;
goto hlfsec2 ;
decfsz DelayCtr1,f ;
goto hlfsec1 ;
return ;

end
;


 
 Re:СОРИ!!!. HELP!!!!!!!!!!!!!!!!!
Автор: Алексей ()
Дата:   16/03/2002 12:08

В I2CTransW нужно поправить проверку на ACK вместо btfsc поставить btfss/
Но этой лшибки не в тестируемой программе.

Замечено следующее при тестирование slave 'DRcp' и выложенного выше мастера:
1. Происходит потеря мастером ACK (при приеме информационных байтов) в следствии
чего он подвисает.
2. Состояние флагов SSPSTAT slave-ы следующее: S=1, D/A=1
3. Еще не производил проверку на переполнение, сейчас посмотрю.
4. Да еще существенно иногда slave принимает "потерянный" для мастера байт,
только мастер почему-то не ловит ACK или slave переполнен. Обычно это бывает
когда пакет, допустим, из 3-х байтов, то мастер зависает на ACK третьего
байта, slave показывает, что он принял 3 информационных байта.

Опять таки с уважением. Еще раз благодарен за ответы.

Алексей.


 
 Re:СПАСИБО!!!!!!!!!!!!!!!!!!!!!! ВСЕМ
Автор: Алексей ()
Дата:   16/03/2002 14:27

Всем ответившим огромное СПАСИБО!!!!!!!
"А Ларчик просто открывался..."
Проблема была в том, что помимо обработки прерывания от SSP, я обрабатывал
прерывание от таймера TMR0. Из-за этого иногда терялся ACK/
Вынос обработчика за пределы прерываний, снял проблему.

НО!!!!!!!!

Иногда все-таки происходит сбой!!! Если у кого была такая проблема, прошу
поделиться решением.

Что происходит:
1. Иногда теряется обмен по шине
2. Иногда цикличность входа в обработку TMR0 происходит с большой задержкой.

Программа основного цикла выглядит так:


Main
banksel PIR1 ; Выбор банка памяти регистра PIR1.
btfss StartBit ; Получен адрес устройства?
goto no_I2C_paket ; НЕТ, на выход.

bsf STATUS,RP0 ; BANK 1.
btfss SSPSTAT,P ; Stop-бит получен?
goto no_I2C_paket ; НЕТ, на выход.

; Посылка прошла успешно. Обработаем послание.

bcf StartBit ;
bcf StopBit ;

pagesel I2C_paket ; Выбираем страницу памяти подпрограммы.
call I2C_paket ; Переходим к обработке пакета.

no_I2C_paket
bcf STATUS,RP0 ; BANK 0.

btfsc INTCON,T0IF ;
call IntTMR0 ;
goto Main ; Повторим все сначала.


 
 Re:СПАСИБО!!!!!!!!!!!!!!!!!!!!!! ВСЕМ
Автор: DRcp ()
Дата:   19/03/2002 09:36

Ваш master и мой slave отработали 30минут - кол-во сбоев = 0...
Всё же дело в той программе где slave, кстати какая тактовая частота у slave
PIC'а? В моём тесте master - 4 МГц, slave - 20 МГц. Попробуйте не обрабатывать
I2C запрос в Main. Кстати если в реальной программе I2C_paket и Main находятся
в разных банках памяти программ и после call I2C_paket нет pagesel то программа
будет улетать не туда.