Witam.
Od dłuższego czasu siedzę nad komunikacją USART synchroniczną pomiędzy ATmega16 i AT90CAN128 i nie potrafię dojść dlaczego nie działa. ATmega16 taktowany jest zewnętrznym kwarcem 3,686400 MHz, a AT90 z wewnętrznego oscylatora RC 8MHz. Docelowo będzie taktowany z pinu OC1A w atmedze, dlatego zdecydowałem się na transmisję synchroniczną. Atmega mierzy napięcie na potencjometrze i temperaturę (DS18B20). Całość wyświetlana jest na LCD. To wszystko śmiga. Napięcie i temperatura będą w przyszłości wysyłane po magistrali CAN przez at90. Chciałem sprawdzić czy komunikacja pomiędzy uP przebiega poprawnie, dlatego gdy przycisnę klawisz podpięty do portu PD7 następuje wysłanie część zmierzonej temperatury (tylko całości) do at90, a ten powinien mi otrzymane dane odesłać. Niestety po naciśnięciu klawisza (PD7) atmega jakby się zawiesza. Tzn. na wyświetlaczu nie wyświetlają się napisy (ODEBRANE DANE itp.) tylko pozostaje widoczny cały czas wcześniejszy tekst. Po zakomentowaniu 2 linii (rs_getch(); temp2=UDR;) program przechodzi dalej powodując zmianę na wyświetlaczu. Nie wiem już co może być źle w programie. Z góry dzięki za wszelkie sugestie co zrobiłem źle.
Kod programu AT90CAN128:
Biblioteka rssynch dla AT90:
Niedziałająca część programu w ATmega16:
Plik rssynch dla ATmega16:
Nie umieściłem całego kodu programu dla ATmega, gdyż ta część co jest wykropkowana działa poprawnie;)
Od dłuższego czasu siedzę nad komunikacją USART synchroniczną pomiędzy ATmega16 i AT90CAN128 i nie potrafię dojść dlaczego nie działa. ATmega16 taktowany jest zewnętrznym kwarcem 3,686400 MHz, a AT90 z wewnętrznego oscylatora RC 8MHz. Docelowo będzie taktowany z pinu OC1A w atmedze, dlatego zdecydowałem się na transmisję synchroniczną. Atmega mierzy napięcie na potencjometrze i temperaturę (DS18B20). Całość wyświetlana jest na LCD. To wszystko śmiga. Napięcie i temperatura będą w przyszłości wysyłane po magistrali CAN przez at90. Chciałem sprawdzić czy komunikacja pomiędzy uP przebiega poprawnie, dlatego gdy przycisnę klawisz podpięty do portu PD7 następuje wysłanie część zmierzonej temperatury (tylko całości) do at90, a ten powinien mi otrzymane dane odesłać. Niestety po naciśnięciu klawisza (PD7) atmega jakby się zawiesza. Tzn. na wyświetlaczu nie wyświetlają się napisy (ODEBRANE DANE itp.) tylko pozostaje widoczny cały czas wcześniejszy tekst. Po zakomentowaniu 2 linii (rs_getch(); temp2=UDR;) program przechodzi dalej powodując zmianę na wyświetlaczu. Nie wiem już co może być źle w programie. Z góry dzięki za wszelkie sugestie co zrobiłem źle.
Kod programu AT90CAN128:
#include<avr/io.h>
#include<compat/deprecated.h>
#include<avr/interrupt.h>
#include "rssynch.h"
signed char temp2=0;
ISR(USART0_RX_vect) //przerwanie gdy odbiór zakończony
{
rs0_getch();
temp2=UDR0;
if(temp2>0)
{
cbi(DDRE, PE2); //sygnał XCK jako wyjście
rs0_putch(temp2); //wyślij otrzymane dane
temp2=0;
}
}
int main()
{
sbi(DDRE, PE2); //XCK jako wejście
rs0_init(600);
UCSR0B=(1<<RXCIE0); //dostępne przerwanie gdy odbiór zakończony
sei();
while(1);
{
}
return 0;
}
Biblioteka rssynch dla AT90:
#include"rssynch.h"
void rs0_init(long int baud)
{
UBRR0H=(unsigned char)((F_CPU/(2*baud)-1)>>8);
UBRR0L=(unsigned char)(F_CPU/(2*baud)-1);
UCSR0B=(1<<RXEN0) | (1<<TXEN0); //odblokowanie: odbiornika, nadajnika
UCSR0C=(1<<UMSEL0) | (3<<UCSZ0) | (1<<UCPOL0);
//praca synchroniczna, tryb 8 bitowy
}
void rs0_putch(unsigned char data)
{
//czekaj aż zwolni się bufor transmisji
while (!(UCSR0A & (1<<UDRE0)));
UDR0=data;
}
unsigned char rs0_getch(void)
{
//czekaj na dane aż zostaną odebrane
while(!(UCSR0A & (1<<RXC0)));
return UDR0;
}
Niedziałająca część programu w ATmega16:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <compat/deprecated.h>
#include <stdio.h>
#include "lcd.h"
#include "ow.h"
#include "rssynch.h"
//******************************************
//**-------- DELKARACJA ZMIENNYCH --------**
//******************************************
unsigned int nap, calk, ulamek; //wynik z przetwornika A/C
char napis[20]; //bufor w którym wyświetlam
unsigned char buf[9]; //bufor 9 bajtowy od temp.
signed char temp; //temperatura całości
int ulamek_temp; //temperatura po przecinku
signed char temp2;
unsigned char tryb=0; //tryb pracy - klawisz 3
//******************************************
//**------------ WYŚWIETLANIE ------------**
//******************************************
void wyswietl()
{
lcd_gotoxy(0,0); //linia 1
switch(tryb)
{
case 0: sprintf(napis,"Napiecie=%1d.%02dV", calk,ulamek);
break;
case 1: sprintf(napis, "ODEBRANE DANE ");
}
lcd_putstr(napis);
lcd_gotoxy(0,1); //linia 2
switch(tryb)
{
case 0: sprintf(napis, "%2d.%02d\xDF\x43 POMIAR",temp,ulamek_temp);
break;
case 1: sprintf(napis, "%2d ", temp2);
}
lcd_putstr(napis);
}
.
.
.
.
int main()
{
DDRB=0xFE; //11 11 11 10 -> PB0 - XCK jako wyjście
PORTB=0x00; //00 00 00 00 -> stan niski na porcie B
DDRC=0x00; //00 00 00 00
PORTC=0x00; //00 00 00 00
DDRD=0x00; //00 00 00 00 -> port D jako wyjście
PORTD=0x8C; //10 00 11 00 -> klawisze na porcie D w stan wysoki
lcd_init(); //inicjalizacja LCD
lcd_cls(); //czyszczenie LCD
init_AC(); //inicjalizacja A/C
rs_init(2400); //inicjalizacja RS'a
.
.
.
.
while(1)
{
if(bit_is_clear(PIND, PD7)) //klawisz 3
{
if(tryb<1)
{
tryb++;
if(tryb)
{
rs_putch(temp);
sbi(DDRB, PB0); //XCK jako wejście
rs_getch();
temp2=UDR;
}
}
else tryb=0;
wyswietl();
do {} //czekaj aż klawisz zostanie puszczony
while(bit_is_clear(PIND, PD7));
}
}
return 0;
}
Plik rssynch dla ATmega16:
#include"rssynch.h"
void rs0_init(long int baud)
{
UBRR0H=(unsigned char)((F_CPU/(2*baud)-1)>>8);
UBRR0L=(unsigned char)(F_CPU/(2*baud)-1);
UCSR0B=(1<<RXEN0) | (1<<TXEN0); //odblokowanie: odbiornika, nadajnika
UCSR0C=(1<<UMSEL0) | (3<<UCSZ0) | (1<<UCPOL0);
//praca synchroniczna, tryb 8 bitowy
}
void rs0_putch(unsigned char data)
{
//czekaj aż zwolni się bufor transmisji
while (!(UCSR0A & (1<<UDRE0)));
UDR0=data;
}
unsigned char rs0_getch(void)
{
//czekaj na dane aż zostaną odebrane
while(!(UCSR0A & (1<<RXC0)));
return UDR0;
}
Nie umieściłem całego kodu programu dla ATmega, gdyż ta część co jest wykropkowana działa poprawnie;)