за основу взял код с немецкого форума, в нем реализован только режим ведомый-приемник на флагах ожидания.
- Код: Выделить всё
$regfile = "M8def.dat" ' the used chip
$crystal = 16000000 ' frequency used
'$baud = 9600 ' brauchen wir nicht
Waitms 100
' TWI init
Gosub Twi_init_slave
Config Servos = 2 , Servo1 = Portb.1 , Servo2 = Portb.2 , Reload = 8
' Ports für Servo auf Ausgang
Config Portb.1 = Output
Config Portb.2 = Output
Config Portd = Output
' Musik, wegen Stimmung usw. :-)
Sound Portb.0 , 300 , 450 ' BEEP
Servo(1) = 100
Servo(2) = 100
Const Maxanzahlbyte = 10 ' Wenn mehr Zeichen kommen werden diese verworfen !
Dim Messagebuf(maxanzahlbyte) As Byte
Dim Anzahlbuf As Byte ' Anzahl Zeichen die gesendet wurden
Dim Neuemsg As Byte ' zeigt an wenn eine neue Message gültig ist
Dim Twi_control As Byte ' Controlregister lokale kopie
Dim Twi_status As Byte
Dim Twi_data As Byte
Const Eigene_slave_adr = &H40 ' Adresse evtl. Anpassen
' wegen der Servos, TWI braucht das hier nicht
Enable Interrupts
Twi_data = 0
Neuemsg = 0 ' Paket ungültig
Anzahlbuf = 0 ' Anzahl empfangener Bytes
Portd = &HFF ' alle LEDs aus
'Print "M8 servo test"
Do
' schauen ob TWINT gesetzt ist
Twi_control = Twcr And &H80 ' Bit7 von Controlregister
If Twi_control = &H80 Then
Twi_status = Twsr And &HF8 ' Status
Portd = Not Twi_status ' test auf die LEDs
Select Case Twi_status
' Slave Adress received, wir sind gemeint !
Case &H60 :
Twcr = &B11000100 ' TWINT löschen, erzeugt ACK
Anzahlbuf = 0
Neuemsg = 0 ' Flag für Message ungültig
' Byte mit ACK
Case &H80 :
If Anzahlbuf < Maxanzahlbyte Then
Incr Anzahlbuf ' zähler +1
Messagebuf(anzahlbuf) = Twdr
End If
Twcr = &B11000100 ' TWINT löschen, erzeugt ACK
' Stop oder restart empfangen
Case &HA0 :
Twcr = &B11000100 ' TWINT löschen, erzeugt ACK
' es müssen 3 Byte sein, damit das Paket OK ist
If Anzahlbuf = 3 Then
Neuemsg = 1 ' Flag für Message gültig
Else
Neuemsg = 0 ' Flag für Message ungültig
End If
' letztes Byte mit NACK, brauchen wir nicht
Case &H88 :
Case &HF8 :
' Fehler, dann reset TWI
Case &H00 :
Twcr = &B11010100 ' TWINT löschen, reset TWI
' was anderes empfangen, sollte nicht vorkommen
Case Else :
Twcr = &B11000100 ' TWINT löschen, erzeugt ACK
End Select
End If
' ein gültiges Paket angekommen
If Neuemsg = 1 Then
Neuemsg = 0 ' Flag wieder löschen
' nur wenn das erste Zeichen ein "S" ist tun wir was damit !
If Messagebuf(1) = "S" Then
Servo(messagebuf(2)) = Messagebuf(3)
Sound Portb.0 , 300 , 450 ' Roger-BEEP
End If
End If
Waitms 10
Loop
End
' TWI als slave aktivieren
Twi_init_slave:
Twsr = 0 ' status und Prescaler auf 0
Twdr = &HFF ' default
Twar = Eigene_slave_adr ' Slaveadresse setzen
Twcr = &B01000100 ' TWI aktivieren, ACK einschalten
Return
переписал на прерываниях и поперчил комментариями:
- Код: Выделить всё
'(
Программа для приема 3х байтных пакетов через TWI
')
$regfile = "M8def.dat"
$crystal = 7372800
$baud = 9600
Config Serialin = Buffered , Size = 20
Waitms 100
Const Max_buf_len = 10 ' максимальный размер буфера(пакета)
Dim Buf(max_buf_len) As Byte
Dim Buf_len As Byte ' текущий размер буфера(пакета)
Dim New_msg As Byte ' флаг нового пакета
Dim Twi_control As Byte
Dim Twi_status As Byte
Dim Twi_data As Byte
Enable Twi
On Twi Twi_int_slave
' TWI init
Gosub Twi_init_slave
Enable Interrupts
Print "M8 twi test"
Do
' если принят новый пакет
If New_msg = 1 Then
New_msg = 0 ' очистить флаг
Print "message: " ; Buf(1) ; " " ; Buf(2) ; " " ; Buf(3) ' вывести первые три байта
End If
Waitms 10
Loop
End
' TWI инициализация слейв - приемник, слейв - передатчик (зависит от старт-пакета)
Twi_init_slave:
Const Twi_slave_adr = &B01110000 ' адрес слейва (наш адрес), TWCG (нулевой бит) сброшен, не распознаем общий вызов(адрес 0x00)
Twi_data = 0
New_msg = 0 ' очищаем пакет
Buf_len = 0
Twsr = 0 ' очищаем статус, частота обмена = fclk/(16 + 2*TWBR*4^TWPS), для ведомого состояние регистров безразлично
Twdr = &HFF ' обнуляем данные
Twar = Twi_slave_adr ' устанавливаем адрес слейва
Reset Twar.twgce ' запрет распознавания общего адреса
Set Twcr.twen ' разрешение работы модуля
Set Twcr.twea ' разрешение автоматической генерации подтверждения
Set Twcr.twint '!!!ВНИМАНИЕ!!!сбрасываем флаг прерывания
Set Twcr.twie ' разрешаем прерывания
Return
Twi_int_slave:
Twi_status = Twsr And &HF8 ' отбрасываем 3 лишних байта [-,TWSP1,TWSP2]
Select Case Twi_status
Case &H60 : ' адресованы
Buf_len = 0
New_msg = 0
Reset Twcr.twsto
Set Twcr.twea
'Twcr = &B11000100
Case &H80: ' приняли байт (их может быть много)
If Buf_len < Max_buf_len Then
Incr Buf_len
Buf(buf_len) = Twdr
Reset Twcr.twsto
Set Twcr.twea
End If
Case &HA0 : 'повстарт или стоп в то время, когда устройство адресовано
' здесь надо бы начать передавать данные
' ежели приняли три байта, то выходим
If Buf_len = 3 Then
New_msg = 1 ' флаг нового сообщения установлен
Else
New_msg = 0 ' флаг нового сообщения сброшен
End If
Reset Twcr.twsta ' освобождаем шину
Reset Twcr.twsto
Set Twcr.twea
'Twcr = &B11000100
Case &H88 : ' устройство уже адресовано, был неверно принят байт данных и послан NACK
Case &HF8 : ' просто пакость в регистрах
Case &H00 : ' ошибка на шине
Reset Twcr.twsta
Set Twcr.twsto
Set Twcr.twea
'Twcr = &B11010100
Case Else:
Twcr = &B01000100 ' перегрузили шину
End Select
Return
в ближайшей перспективе будет режим ведомый-передатчик.