Микроконтроллеры, АЦП, память и т.д Темы касающиеся микроконтроллеров разных производителей, памяти, АЦП/ЦАП, периферийных модулей... |
01.09.2007, 13:02
|
|
Временная регистрация
Регистрация: 09.02.2007
Сообщений: 91
Сказал спасибо: 0
Сказали Спасибо 5 раз(а) в 5 сообщении(ях)
|
ATMega8 + 24C512
Память связана с МК по TWI, A0 и A1 памяти кинул на землю, т.е. адрес устройства = 0.
В даташите указано, что читать последовательно байт за байтом надо следующим образом:
1) Байт с адресом устройства + бит R/W=1 (чтение)
2) получить ADDR_ACK
3) читать байт из памяти
4) получить DATA_ACK
5) goto п. 3 (читать сколько надо)
6) выдать STOP байт
почему-то не нарисовано, что сначала надо выдать START - байт.
Так вот, если надо прочитать 1 байт - без проблемм, хоть всю память по 1 байту, а если надо несколько байт читать, то 1 байт читается, а остальные все $FF.
Исходники:
---------------------------------------------
;************************************************* *******************
;* TWI
;************************************************* *******************
;------------------------------------------------------------------------------------------
TWIhandler:
reti
;------------------------------------------------------------------------------------------
; Обработка ошибок реализована след. образом:
; 1) Процедуры I2Cxx возвращают CF=1 в случае ошибки
; 2) Процедуры более высокого уровня должны просто проверять CF
.equ DEV_ADR_W = 0xA0 ;адрес устройства №0 при записи
.equ DEV_ADR_R = 0xA1 ;адрес устройства №0 при чтении
.equ START = 0x08 ;послан START
.equ STARTR = 0x10 ;послан повтор START
.equ ADDR_ACK = 0x18 ;Подтверждение адреса+ACK при записи
.equ R_ADDR_ACK = 0x40 ;Подтверждение адреса+ACK при чтении
.equ DATA_ACK = 0x28 ;Подтверждение DATA+ACK при записи
.equ BUF =$120 ;буфер в SRAM
;------------------------------------------------------------------------------------------
InitI2C:
; Настройка порта на чтение
cbi DDRC, 0
cbi DDRC, 1
;ldi temp0, 10 ;~300 для 12 МГц
;ldi temp0, 32 ; 100KHz для 8МГц
ldi temp0, 52 ; 100KHz для 16МГц
out TWBR, temp0
cbi TWSR, 0
cbi TWSR, 1
ret
;------------------------------------------------------------------------------------------
WaitI2C:
in temp0,TWCR
sbrs temp0,TWINT
rjmp WaitI2C
ret
;------------------------------------------------------------------------------------------
; Send START
; OUT - temp0 = status code
I2CStart:
clc ;CF=0
ldi temp0, (1‹‹TWINT)|(1‹‹TWSTA)|(1‹‹TWEN)
out TWCR, temp0
rcall WaitI2C
;проверить статус
in temp0,TWSR
andi temp0, 0xF8 ;mask prescale bytes
cpi temp0,START
breq I2CS
cpi temp0, STARTR
breq I2CS
sec ;CF=1
I2CS:
ret
;-------------------------------------------------------------------
; Send STOP
I2CStop:
clc
ldi temp0, (1‹‹TWINT)|(1‹‹TWEN)| (1‹‹TWSTO)
out TWCR, temp0
ret
;-------------------------------------------------------------------
; Send Device0 address for write
; OUT - temp0 = status code
I2CSetDevAddrW:
clc ;CF=0
;Device Address to write bits A0=A1=0, R/W bit=0
ldi temp0, DEV_ADR_W
out TWDR, temp0
ldi temp0, (1‹‹TWINT) | (1‹‹TWEN)
out TWCR, temp0
rcall WaitI2C
;проверить статус
in temp0,TWSR
andi temp0, 0xF8 ;mask prescale bytes
cpi temp0, ADDR_ACK
breq I2CSDAW
sec
I2CSDAW:
ret
;-------------------------------------------------------------------
; Send Device0 address for read
; OUT - temp0 = status code
I2CSetDevAddrR:
clc ;CF=0
;Device Address for read
ldi temp0, DEV_ADR_R ;bits A0=A1=0, R/W bit=1
out TWDR, temp0
ldi temp0, (1‹‹TWINT) | (1‹‹TWEN)
out TWCR, temp0
rcall WaitI2C
in temp0,TWSR
andi temp0, 0xF8
cpi temp0, R_ADDR_ACK
breq I2CSDAR
sec ;CF=1
I2CSDAR:
ret
;-------------------------------------------------------------------
; Send Data
; IN - temp1
; OUT - temp0 = status code
I2CSendByte:
clc ;CF=0
out TWDR, temp1
ldi temp0, (1‹‹TWINT) | (1‹‹TWEN)
out TWCR, temp0
rcall WaitI2C
in temp0,TWSR
andi temp0, 0xF8
cpi temp0, DATA_ACK
breq I2CSB
sec ;CF=1
I2CSB:
ret
;-------------------------------------------------------------------
; Read Data
; OUT - temp0 = status code
; OUT - temp1 = byte
I2CReadByte:
clc ;CF=0
ldi temp0, (1‹‹TWINT) | (1‹‹TWEN)
out TWCR, temp0
rcall WaitI2C
in temp0,TWSR
; 0x50, 0x58 - корректные значения
; если маска 0xF0, тогда только 0x50
andi temp0, 0xF0
cpi temp0, 0x50
brne I2CRBE
in temp1, TWDR
ret
I2CRBE:
sec ;CF=1
ret
;************************************************* *******************
; End TWI
;************************************************* *******************
; ----------------------------------------
DoReadI2C:
lds temp2,InputBufferBegin+4 ;Lo byte of firs parameter (Address)
lds temp3,InputBufferBegin+5 ;Hi byte of firs parameter
ldi temp1,1 ;answer from RAM
mov RAMread,temp1
rcall I2CStart ;after call, in temp0 - status
brcs DRCErr ;if CF=1 then exit
rcall I2CSetDevAddrW;set device address for write
brcs DRCErr ;if CF=1 then exit
mov temp1,temp3 ;Hi byte
rcall I2CSendByte ;EEPROM Hi address
brcs DRCErr ;if CF=1 then exit
mov temp1,temp2 ;Lo byte
rcall I2CSendByte ;EEPROM Lo address
brcs DRCErr
rcall I2CStart
rcall I2CSetDevAddrR;set device address for read
brcs DRCErr ;if CF=1 then exit
rcall I2CReadByte
brcs DRCErr ;if CF=1 then exit
clr temp0 ;reset status
sts BUF+1,temp1 ;save byte
DRCErr:
sts BUF,temp0 ;save status
rcall I2CStop
ldi ZH, high(BUF) ;ROMpointer to descriptor
ldi ZL, low(BUF)
ldi temp0,2 ;byte1=staus, byte2=EEPROM
rjmp ComposeEndXXXDescriptor
;-------------------------------------------------------------------
DoReadI2CBuf:
lds temp2,InputBufferBegin+4 ;Lo byte of firs parameter
lds temp3,InputBufferBegin+5 ;Hi byte of firs parameter
lds temp1,InputBufferBegin+6 ;count
push temp1
ldi temp1,1 ;answer from RAM
ldi temp1,1 ;answer from RAM
mov RAMread,temp1
rcall I2CStart ;after call, in temp0 - status
brcs DRCBErr ;if CF=1 then exit
rcall I2CSetDevAddrW;set device address for write
brcs DRCBErr ;if CF=1 then exit
mov temp1,temp3 ;Hi byte
rcall I2CSendByte ;EEPROM Hi address
brcs DRCBErr ;if CF=1 then exit
mov temp1,temp2 ;Lo byte
rcall I2CSendByte ;EEPROM Lo address
brcs DRCBErr
ldi ZL,low(BUF+2)
ldi ZH,high(BUF+2);
pop temp1 ;restore count
mov temp2,temp1
push temp1 ;on exit already used pop
sts BUF+1,temp2
rcall I2CStart
rcall I2CSetDevAddrR;set device address for read
brcs DRCBErr ;if CF=1 then exit
I2RB:
rcall I2CReadByte
brcs DRCBErr ;if CF=1 then exit
st Z+,temp1 ;save byte
dec temp2
brne I2RB
clr temp0 ;reset status
DRCBErr:
sts BUF,temp0 ;save status
rcall I2CStop
ldi ZH, high(BUF) ;ROMpointer to descriptor
ldi ZL, low(BUF)
pop temp1 ;restore temp1
mov temp0,temp1 ;byte1=staus, byte2=EEPROM
inc temp0
inc temp0
rjmp ComposeEndXXXDescriptor
|
|
|
|
01.09.2007, 14:04
|
|
Почётный гражданин KAZUS.RU
Регистрация: 06.02.2007
Сообщений: 1,340
Сказал спасибо: 3
Сказали Спасибо 106 раз(а) в 66 сообщении(ях)
|
Re: ATMega8 + 24C512
Сообщение от pve70
|
1) Байт с адресом устройства + бит R/W=1 (чтение)
2) получить ADDR_ACK
3) читать байт из памяти
4) получить DATA_ACK
5) goto п. 3 (читать сколько надо)
6) выдать STOP байт
почему-то не нарисовано, что сначала надо выдать START - байт.
Так вот, если надо прочитать 1 байт - без проблемм, хоть всю память по 1 байту, а если надо несколько байт читать, то 1 байт читается, а остальные все $FF.
|
Попробуйте рестарт после 4 пункта
|
|
|
|
01.09.2007, 16:51
|
|
Временная регистрация
Регистрация: 09.02.2007
Сообщений: 91
Сказал спасибо: 0
Сказали Спасибо 5 раз(а) в 5 сообщении(ях)
|
Если по алгоритму
1)START
2)Адрес устройства +W
3)Получить ADDR_ACK
4)Hi адрес EEPROM
5)DATA_ACK
6)Lo адрес EEPROM
7)DATA_ACK
START
9)Адрес устройства +R
10) Читать байт
11)STOP
12)goto
то работает, но это алгоритм "Current Read" из даташита. А без повторения каждый раз п.8,9,12 - это
по даташиту алгоритм последовательного чтения. Он то и неработает!
|
|
|
|
01.09.2007, 17:16
|
|
Временная регистрация
Регистрация: 09.02.2007
Сообщений: 91
Сказал спасибо: 0
Сказали Спасибо 5 раз(а) в 5 сообщении(ях)
|
в п.12 написал goto 8 и скобочку а оне рожу изобразили!
|
|
|
|
01.09.2007, 18:16
|
|
Почётный гражданин KAZUS.RU
Регистрация: 06.02.2007
Сообщений: 1,340
Сказал спасибо: 3
Сказали Спасибо 106 раз(а) в 66 сообщении(ях)
|
поставь рестарт после приема очередного байта, без выдачи адреса, без стопа, он там сам инкременируется.
Я же выше постил. Сам с собой разговариваю ?
|
|
|
|
01.09.2007, 20:01
|
|
Временная регистрация
Регистрация: 09.02.2007
Сообщений: 91
Сказал спасибо: 0
Сказали Спасибо 5 раз(а) в 5 сообщении(ях)
|
Извини, не понял сразу.
рестарт - это START выдать:
в TWCR (1‹‹TWINT)|(1‹‹TWSTA)|(1‹‹TWEN) ?
|
|
|
|
01.09.2007, 21:02
|
|
Почётный гражданин KAZUS.RU
Регистрация: 06.02.2007
Сообщений: 1,340
Сказал спасибо: 3
Сказали Спасибо 106 раз(а) в 66 сообщении(ях)
|
да, совершенно правильно, рестарт и старт - это одно и то же. sda из 1 в 0 при высоком уровне scl.
Тоже только что задумался, почему их по разному называют.
Смотрю свой листинг - страничное чтение из 24с32
-старт
-send a0 // выдача записи в устройство
-send 00 // выдача старшего адреса
-send adres // выдача младшего адреса, откуда будем читать
loop // цикл чтения n байтов
-start // рестарт
-send a1 // задаем чтение по ранее записанному адресу
-read byte // читаем очередной байт, выдаеи аск
- n-1
if n›0 goto loop // пока байты не закончились, повторяем
-stop
Код вроде рабочий, но давно дело было.
Почему в цикле send a1, не знаю, его же вроде 1 раз можно воткнуть.
|
|
|
|
01.09.2007, 21:17
|
|
Временная регистрация
Регистрация: 09.02.2007
Сообщений: 91
Сказал спасибо: 0
Сказали Спасибо 5 раз(а) в 5 сообщении(ях)
|
Я привел мой рабочий код. В даташите тоже написано, что A1 один раз выдавать надо, а затем читать n байт, но на деле только так и работает. Вот и вопрос возник.
|
|
|
|
01.09.2007, 21:21
|
|
Почётный гражданин KAZUS.RU
Регистрация: 06.02.2007
Сообщений: 1,340
Сказал спасибо: 3
Сказали Спасибо 106 раз(а) в 66 сообщении(ях)
|
Сообщение от pve70
|
START
9)Адрес устройства +R
10) Читать байт
11)STOP
12)goto
|
Стоп перед циклом быть не должен.
И у меня же страница читалась.
|
|
|
|
01.09.2007, 21:36
|
|
Временная регистрация
Регистрация: 09.02.2007
Сообщений: 91
Сказал спасибо: 0
Сказали Спасибо 5 раз(а) в 5 сообщении(ях)
|
Да, без STOP работает.
Вот картинка из документации
-- Прилагается рисунок: --
|
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Тема |
Автор |
Раздел |
Ответов |
Последнее сообщение |
Atmega8 и tiny2313
|
NA1S |
Микроконтроллеры, АЦП, память и т.д |
1 |
13.12.2008 09:43 |
LabVIEW + Atmega8
|
Master-rza |
Микроконтроллеры, АЦП, память и т.д |
8 |
09.12.2008 13:41 |
Mega8 & eeprom 24c512
|
Mast |
Микроконтроллеры, АЦП, память и т.д |
5 |
31.05.2008 00:54 |
AVR постраничная запись памяти 24C512?
|
Andrewg |
Микроконтроллеры, АЦП, память и т.д |
0 |
08.08.2007 14:34 |
ATMEGA8-16PU
|
Pit10 |
Микроконтроллеры, АЦП, память и т.д |
3 |
09.11.2006 12:12 |
Часовой пояс GMT +4, время: 06:01.
|
|