Bumbum
12.03.2013, 17:31
Hallo,
ich bin an der Entwicklung eines Programms für einen Tiny25. Ich bentöige dabei Werte, die ich über den integrierten ADC einlese irgendwo angezeigt. Da der Tiny25 so wenige Pins hat habe ich mir überlegt diese Werte über die ISP-Schnittstelle zu senden, da ich diese eh "onboard" habe um den Controller darüber zu programmieren.
Meine Idee war es also einen kleinen Umsetzer zu bauen, der mir die ISP-Daten auf eine serielel Schnittstelle übersetzt und umgekehrt. Für dieses Projekt habe ich einen Tiny2313 verwendet, da der noch rumlag. Die ISP-Schnittstelle ist ebenfalls so verdrahtet, dass ich den Tiny2313 darüber programmieren kann mit der Ausnahme das ich die Reset-Leitung per Jumper trennen kann und die Reset-Leitung von "außen" auf einen Eingangspin geht, damit ich die ISP-Schnittstelle abschalten kann solange der Tiny25 programmiert wird. Wenn also der externe Reset auf Low geht möchte ich die ISP-Schnittstelle abschalten.
Leider ist aus den Datenblättern für mich nicht so ganz ersichtlich wie ich das ganze programmieren soll. Den Umsetzer mit dem Tiny2313 habe ich mir als ISP-Slave gedacht. Hier mal mein Code dafür:
#define AVRGCC/**
ISP_RS232:
Interface um Daten zwischen ISP und RS232 zu übersetzen.
IO:
PB0 out LED gelb (Daten RS232 vorhanden)
PB1 out LED grün (Daten ISP vorhanden)
PB2 frei
PB3 frei
PB4 frei
PB5 MOSI
PB6 MISO
PB7 SCK
PD0 RXD
PD1 TXD
PD2 in disable (ext. Reset)
PD3 frei
PD4 frei
PD5 frei
PD6 Out LED rot (Buffer Überlauf)
**/
#include <avr/io.h>
#include <compiler.h>
#include <avr/interrupt.h>
//F_CPU = 8000000
#define BAUD 9600l
#define UBRRValue (F_CPU / (BAUD * 16) - 1)
#define BufferSize 16
#define LED_ge_0 PORTB = ~(~PORTB | (1<<PB0))
#define LED_ge_1 PORTB = (PORTB | (1<<PB0))
#define LED_gn_0 PORTB = ~(~PORTB | (1<<PB1))
#define LED_gn_1 PORTB = (PORTB | (1<<PB1))
#define LED_rt_0 PORTD = ~(~PORTD | (1<<PD6))
#define LED_rt_1 PORTD = (PORTD | (1<<PD6))
#define disable ((PIND & 1<<PD2) == 0)
#define RS232ready ((UCSRA & (1<<UDRE)) != 0)
#define AccessRead 0
#define AccessWrite 1
#define BufferRS232 0
#define BufferISP 1
volatile bool currentState = FALSE;
volatile U8 InBuffer[2][BufferSize];
volatile U8 Pointer[2][2];
void sendMsg (char *Msg, bool addCR)
{
while (*Msg != 0)
{
while ( !(UCSRA & (1<<UDRE)));
UDR = *Msg++;
}
if (addCR)
sendMsg ("\r\n", FALSE);
}
void incPointer (U8 Buffer, U8 Access)
{
if (++Pointer[Buffer][Access] >= BufferSize)
Pointer[Buffer][Access] = 0;
}
bool BufferDone (U8 Buffer)
{
return (Pointer[Buffer][AccessRead] == Pointer[Buffer][AccessWrite]);
}
void add2Buffer (U8 Buffer, U8 value)
{
U8 tmp = Pointer[Buffer][AccessWrite];
if (++tmp >= BufferSize)
tmp = 0;
if (tmp != Pointer[Buffer][AccessRead])
{
Pointer[Buffer][AccessWrite] = tmp;
InBuffer[Buffer][tmp] = value;
}
else
LED_rt_1;
}
U8 readBuffer (U8 Buffer)
{
return (InBuffer[Buffer][AccessRead]);
}
ISR (USART_RX_vect)
{
add2Buffer (BufferRS232, UDR);
}
ISR (USI_OVERFLOW_vect)
{
U8 value = USIDR;
if (currentState)
{
add2Buffer (BufferISP, value);
if (!BufferDone (BufferRS232))
incPointer (BufferRS232, AccessRead);
if (!BufferDone (BufferRS232))
USIDR = readBuffer (BufferRS232);
else
USIDR = 0;
}
else
LED_rt_1;
}
int main (void)
{
DDRB = 0b00000011;
PORTB = 0b00000000;
DDRD = 0b01000000;
PORTD = 0b00000000;
UCSRB = (1<<RXCIE) | (1<<TXEN) | (1<<RXEN);
UCSRC = (1<<UCSZ1) | (1<<UCSZ0);
UBRRH = (U8)(UBRRValue>>8);
UBRRL = (U8)UBRRValue;
Pointer[BufferRS232][AccessRead] = 0;
Pointer[BufferRS232][AccessWrite] = 0;
Pointer[BufferISP][AccessRead] = 0;
Pointer[BufferISP][AccessWrite] = 0;
sei ();
sendMsg ("", TRUE);
sendMsg ("RESET", TRUE);
while (1)
{
if (disable)
{
if (currentState)
{
USICR = 0;
sendMsg ("TARGET RESET", TRUE);
}
currentState = FALSE;
}
else
{
if (!currentState)
{
USICR = (1<<USIWM0) | (1<<USICS1) | (1<<USICLK) |(1<<USIOIE);
sendMsg ("TARGET START", TRUE);
if (!BufferDone (BufferRS232))
USIDR = readBuffer (BufferRS232);
else
USIDR = 0;
}
currentState = TRUE;
}
if (RS232ready & !BufferDone (BufferISP))
{
UDR = readBuffer (BufferISP);
incPointer (BufferISP, AccessRead);
}
if (BufferDone (BufferISP))
LED_gn_0;
else
LED_gn_1;
if (BufferDone (BufferRS232))
LED_ge_0;
else
LED_ge_1;
}
return (0);
}
Die RS232-Kommunikation läuft. RESET wird gemeldet und TARGET RESET bzw. TARGET START wird auch gemeldet. Und wenn ich etwas sende geht die gelbe LED als Anzeige an, dass etwas im RS232-Buffer vorhanden ist. (Nach 16 Bytes geht dann auch die rote LED an)
Der Tiny25 soll dann als ISP-Master funktionieren. Hier mal mein Test-Code um etwas zu senden:
#define AVRGCC
/**
Voltage Detector:
IO:
PB0 MOSI
PB1 MISO out LED
PB2 SCK
PB3 analog in (ADC3)
PB4 frei
**/
#include <avr/io.h>
#include <util/delay.h>
#include <compiler.h>
//F_CPU = 1000000
#define LED0 PORTB = ~(~PORTB | (1<<PB1))
#define LED1 PORTB = (PORTB | (1<<PB1))
int get_analog_input (void)
{
ADCSRA |= (1<<ADSC);
while ((ADCSRA & (1<<ADSC)) > 0);
return ((ADCH<<8) | ADCL) - 512;
}
int main (void)
{
DDRB = 0b00000010;
PORTB = 0b00000000;
DIDR0 = (1<<ADC3D);
ADMUX = (1<<REFS1) | (1<<REFS2) | (1<<MUX1) | (1<<MUX0);
ADCSRA = (1<<ADEN);
USICR = (1<<USIWM0);
USIDR = 'A';
U8 i1;
for (i1 = 0; i1 < 8; i1++)
{
USICR |= (1<<USICLK);
_delay_ms (1);
}
while (1);
return (0);
}
Leider kommt beim Umsetzer nichts an (grüne LED bleibt aus). Wenn ich den Tiny25 programmiere erkennt der Umsetzer aber brav die Reset-Leitung und meldet "TARGET RESET" und "TARGET START".
Wo könnte mein Problem liegen? Liegt es an der Verdrahtung? Kann ich vielleicht gar keine Kommunikation bei einer 1:1 verdrahteten ISP-Schnittstelle aufbauen? So wie ich das Verstehe müsste es gehen, da die Pins ja MISO (Master In Slave Out) und MOSI (Master Out und Slave In) heißen. Allerdings habe ich in der Beschreibung der Register für die USI-Schnittstelle nirgendwo gesehen wie ich Master und Slave konfiguriere.
Viele Grüße
Andreas
ich bin an der Entwicklung eines Programms für einen Tiny25. Ich bentöige dabei Werte, die ich über den integrierten ADC einlese irgendwo angezeigt. Da der Tiny25 so wenige Pins hat habe ich mir überlegt diese Werte über die ISP-Schnittstelle zu senden, da ich diese eh "onboard" habe um den Controller darüber zu programmieren.
Meine Idee war es also einen kleinen Umsetzer zu bauen, der mir die ISP-Daten auf eine serielel Schnittstelle übersetzt und umgekehrt. Für dieses Projekt habe ich einen Tiny2313 verwendet, da der noch rumlag. Die ISP-Schnittstelle ist ebenfalls so verdrahtet, dass ich den Tiny2313 darüber programmieren kann mit der Ausnahme das ich die Reset-Leitung per Jumper trennen kann und die Reset-Leitung von "außen" auf einen Eingangspin geht, damit ich die ISP-Schnittstelle abschalten kann solange der Tiny25 programmiert wird. Wenn also der externe Reset auf Low geht möchte ich die ISP-Schnittstelle abschalten.
Leider ist aus den Datenblättern für mich nicht so ganz ersichtlich wie ich das ganze programmieren soll. Den Umsetzer mit dem Tiny2313 habe ich mir als ISP-Slave gedacht. Hier mal mein Code dafür:
#define AVRGCC/**
ISP_RS232:
Interface um Daten zwischen ISP und RS232 zu übersetzen.
IO:
PB0 out LED gelb (Daten RS232 vorhanden)
PB1 out LED grün (Daten ISP vorhanden)
PB2 frei
PB3 frei
PB4 frei
PB5 MOSI
PB6 MISO
PB7 SCK
PD0 RXD
PD1 TXD
PD2 in disable (ext. Reset)
PD3 frei
PD4 frei
PD5 frei
PD6 Out LED rot (Buffer Überlauf)
**/
#include <avr/io.h>
#include <compiler.h>
#include <avr/interrupt.h>
//F_CPU = 8000000
#define BAUD 9600l
#define UBRRValue (F_CPU / (BAUD * 16) - 1)
#define BufferSize 16
#define LED_ge_0 PORTB = ~(~PORTB | (1<<PB0))
#define LED_ge_1 PORTB = (PORTB | (1<<PB0))
#define LED_gn_0 PORTB = ~(~PORTB | (1<<PB1))
#define LED_gn_1 PORTB = (PORTB | (1<<PB1))
#define LED_rt_0 PORTD = ~(~PORTD | (1<<PD6))
#define LED_rt_1 PORTD = (PORTD | (1<<PD6))
#define disable ((PIND & 1<<PD2) == 0)
#define RS232ready ((UCSRA & (1<<UDRE)) != 0)
#define AccessRead 0
#define AccessWrite 1
#define BufferRS232 0
#define BufferISP 1
volatile bool currentState = FALSE;
volatile U8 InBuffer[2][BufferSize];
volatile U8 Pointer[2][2];
void sendMsg (char *Msg, bool addCR)
{
while (*Msg != 0)
{
while ( !(UCSRA & (1<<UDRE)));
UDR = *Msg++;
}
if (addCR)
sendMsg ("\r\n", FALSE);
}
void incPointer (U8 Buffer, U8 Access)
{
if (++Pointer[Buffer][Access] >= BufferSize)
Pointer[Buffer][Access] = 0;
}
bool BufferDone (U8 Buffer)
{
return (Pointer[Buffer][AccessRead] == Pointer[Buffer][AccessWrite]);
}
void add2Buffer (U8 Buffer, U8 value)
{
U8 tmp = Pointer[Buffer][AccessWrite];
if (++tmp >= BufferSize)
tmp = 0;
if (tmp != Pointer[Buffer][AccessRead])
{
Pointer[Buffer][AccessWrite] = tmp;
InBuffer[Buffer][tmp] = value;
}
else
LED_rt_1;
}
U8 readBuffer (U8 Buffer)
{
return (InBuffer[Buffer][AccessRead]);
}
ISR (USART_RX_vect)
{
add2Buffer (BufferRS232, UDR);
}
ISR (USI_OVERFLOW_vect)
{
U8 value = USIDR;
if (currentState)
{
add2Buffer (BufferISP, value);
if (!BufferDone (BufferRS232))
incPointer (BufferRS232, AccessRead);
if (!BufferDone (BufferRS232))
USIDR = readBuffer (BufferRS232);
else
USIDR = 0;
}
else
LED_rt_1;
}
int main (void)
{
DDRB = 0b00000011;
PORTB = 0b00000000;
DDRD = 0b01000000;
PORTD = 0b00000000;
UCSRB = (1<<RXCIE) | (1<<TXEN) | (1<<RXEN);
UCSRC = (1<<UCSZ1) | (1<<UCSZ0);
UBRRH = (U8)(UBRRValue>>8);
UBRRL = (U8)UBRRValue;
Pointer[BufferRS232][AccessRead] = 0;
Pointer[BufferRS232][AccessWrite] = 0;
Pointer[BufferISP][AccessRead] = 0;
Pointer[BufferISP][AccessWrite] = 0;
sei ();
sendMsg ("", TRUE);
sendMsg ("RESET", TRUE);
while (1)
{
if (disable)
{
if (currentState)
{
USICR = 0;
sendMsg ("TARGET RESET", TRUE);
}
currentState = FALSE;
}
else
{
if (!currentState)
{
USICR = (1<<USIWM0) | (1<<USICS1) | (1<<USICLK) |(1<<USIOIE);
sendMsg ("TARGET START", TRUE);
if (!BufferDone (BufferRS232))
USIDR = readBuffer (BufferRS232);
else
USIDR = 0;
}
currentState = TRUE;
}
if (RS232ready & !BufferDone (BufferISP))
{
UDR = readBuffer (BufferISP);
incPointer (BufferISP, AccessRead);
}
if (BufferDone (BufferISP))
LED_gn_0;
else
LED_gn_1;
if (BufferDone (BufferRS232))
LED_ge_0;
else
LED_ge_1;
}
return (0);
}
Die RS232-Kommunikation läuft. RESET wird gemeldet und TARGET RESET bzw. TARGET START wird auch gemeldet. Und wenn ich etwas sende geht die gelbe LED als Anzeige an, dass etwas im RS232-Buffer vorhanden ist. (Nach 16 Bytes geht dann auch die rote LED an)
Der Tiny25 soll dann als ISP-Master funktionieren. Hier mal mein Test-Code um etwas zu senden:
#define AVRGCC
/**
Voltage Detector:
IO:
PB0 MOSI
PB1 MISO out LED
PB2 SCK
PB3 analog in (ADC3)
PB4 frei
**/
#include <avr/io.h>
#include <util/delay.h>
#include <compiler.h>
//F_CPU = 1000000
#define LED0 PORTB = ~(~PORTB | (1<<PB1))
#define LED1 PORTB = (PORTB | (1<<PB1))
int get_analog_input (void)
{
ADCSRA |= (1<<ADSC);
while ((ADCSRA & (1<<ADSC)) > 0);
return ((ADCH<<8) | ADCL) - 512;
}
int main (void)
{
DDRB = 0b00000010;
PORTB = 0b00000000;
DIDR0 = (1<<ADC3D);
ADMUX = (1<<REFS1) | (1<<REFS2) | (1<<MUX1) | (1<<MUX0);
ADCSRA = (1<<ADEN);
USICR = (1<<USIWM0);
USIDR = 'A';
U8 i1;
for (i1 = 0; i1 < 8; i1++)
{
USICR |= (1<<USICLK);
_delay_ms (1);
}
while (1);
return (0);
}
Leider kommt beim Umsetzer nichts an (grüne LED bleibt aus). Wenn ich den Tiny25 programmiere erkennt der Umsetzer aber brav die Reset-Leitung und meldet "TARGET RESET" und "TARGET START".
Wo könnte mein Problem liegen? Liegt es an der Verdrahtung? Kann ich vielleicht gar keine Kommunikation bei einer 1:1 verdrahteten ISP-Schnittstelle aufbauen? So wie ich das Verstehe müsste es gehen, da die Pins ja MISO (Master In Slave Out) und MOSI (Master Out und Slave In) heißen. Allerdings habe ich in der Beschreibung der Register für die USI-Schnittstelle nirgendwo gesehen wie ich Master und Slave konfiguriere.
Viele Grüße
Andreas