Nefunkční přerušení USART - ATmega8 1 MHz, příjem přes RS232

Na ATmega8 na frekvenci interního oscilátoru 1 MHz se snažím po RS232 poslat znak a pak aby mi ho poslal zpět. Čip bliká ale neodpovídá

#include <avr/io.h>
#include <inttypes.h>
#include <avr/interrupt.h>
#include <util/delay.h>

// get char
unsigned char uart_getc( void )
{
	
	/* Wait for data to be received */
	while ( !(UCSRA & (1<<RXC)) )
	;
	/* Get and return received data from buffer */
	return UDR;
}
// send char
void uart_putc(unsigned char data )
{
	while ( !( UCSRA & (1<<UDRE)) )
	;
	UDR = data;
	
}
// Přerušení USART
ISR (USART_RXC_vect) {
	unsigned char znak;
	znak = uart_getc();
	PORTD ^= 0x80;
	uart_putc(znak);
	
}

int main(void)
{
	
	
	/***** inicializace uart  *****/
	DDRD = 0x80;
	PORTD = 0x00;
	
	UCSRA = 0x00;
	UBRRH = 0x00;  // nastaveni rychlosti pro krystal  1 MHz
	UBRRL = 12;    // (v pripade taktovani 8 MHz zde pouzijte  UBRRL = 0x33; )
	UCSRB = 0x89;  // povolit vysilani, prijem a přerušení
	UCSRC = 0x86;  // ramec dat:  8 datovych, 1 stop bit, bez parity
	sei();
	
	while(1)
	{
		PORTD ^= 0x80;
		_delay_ms(500);
	}
}

:arrow_right: administrator: přejmenováno z "Nefunkční přerušení USART"

v obsluhe prerusenia od Rx uz nemusis volat ziadnu dalsiu funkciu, ktora caka na prijatie. mam na mysli toto: while ( !(UCSRA & (1<<RXC)) )
Ked ti nastane to prerusenie od Rx, data su uz prijate.
takze ti staci spravit:

[code]// Přerušení USART
ISR (USART_RXC_vect) {
unsigned char znak;
znak = UDR;
PORTD ^= 0x80;
uart_putc(znak);

}[/code]
Na tie nastavenia UART sa este idem pozriet, lebo takto ako mas nastavene bity sa v tom nevyznam.

EDIT: nemas nastaveny RXEN. musis ho mat nastaveny, aby si mohol prijimat. Mas nastaveny TXB8. neviem presne co to je, nepouzivam to. Na zaciatok to vynechaj. Zapis ako pouzivas je neprehladny a tazko sa v nom hlada chyba. Nauc sa to pisat takto (len odporucam, nenutim ta):

UCSRB |= (1<<TXEN) | (1<<RXEN) | (1<<RXCIE);

Nastavujes si tak kazdy bit zvlast, a je to prehladne.

To bude tím, že máš chybu v inicializaci UARTu odesíláš 0x89 => RXCIE, TXEN a TX8.

Máš tam mít 0x98 => RXCIE, RXEN a TXEN.

Chlapi, ak chcete aby sa nikto cudzi vyznal vo vasich programoch a vyznali sa aj vy sami, piste nastavovanie bitov zrozumitelne. Nevraviac o tom, ze ked pouzitjete iny mcu ktory moze mat poprehadzovane bity, program vam nebude fungovat a vy budete dlho luskat ze preco a ci nahodou nie je na vine
vadny mcu.

Tie bity maju pre zrozumitelnost aj svoje oznacenie, ktoremu je priradena bitova hodnota v prislusnom *.h subore od vyrobcu. Tento *.h subor sa includuje automaticky v ramci projektu (napr. v AVRstudiu) a tak sa netreba o nic starat. Samozrejme, ak bity nie su v trochu inych registroch. Ako napriklad pre ATega324, ktora ma dva UARTY, nie je register UDR oznazeny ako UDR ale ako UDR0 a UDR1.

priklad pre atmega8:

v tomto subore je vsetko potrebne z hw zadefinovane:

iom8.h


// priklad nastavenia podla vyssie uvedeneho odporucania pre UART
UCSRB = (1<<RXCIE) + (1<<RXEN) + (1<<TXEN);
// alebo
UCSRB = (1<<RXCIE) | (1<<RXEN) | (1<<TXEN);
// oba riadky davaju identicky vysledok

Ak budete pouzitvat v o svojich kodoch kontrukcie typu

   UCSRB = 0x89;  // povolit vysilani, prijem a přerušení

vy sa v tom mozno budete “vyznat” ako napriklad v tomto pripade, ale hned z fleku odradite 90% potencionalne ochotnych poradit od analyzy kodu.

Už to funguje, ale vracej se mi nějak divně data.
Přijatý data ; Odeslaný data
224 ; 1
128 ; 2
224 ; 3
134 ; 4
248 ; 5
134 ; 6
248 ; 7
128 ; 8
224 ; 9
128 ; 0
Ale nevím jestli je to programem v počítači nebo na čipu.

Ještě by ses mohl podělit s tím, kam to posíláš a odkud se ti to vrací?Tedy co máš v tom počítači za program s kterým komunikuješ?

Pravděpodobně nemáš nastavené stejně přenosové rychlosti.

Jinak všem , kdo začínají experimentovat s USARTem doporučuju nainstalovat nějaký terminál - Hyperterminal je na prd, takový nešikovný - já používám Docklight a k tomu pro kontrolu monitorování portu za pomoci Com Spy.

Na ebay je převodník USB/USART za hubičku.

A máš v PC nastavenou rychlost stejně jako v mcu ?
Tedy 4800bd, 8 bitů, 1 stop, bez parity ?
Máš MCU skutečně na IntRC 1 MHz ?

Navíc bych zjednodušil obsluhu přerušení :

// Přerušení USART
ISR (USART_RXC_vect) {
   unsigned char znak;
   znak = UDR;
   PORTD ^= 0x80;
   UDR = znak;
   
}	

Část programu které se to týká

Private Sub Button4_Click(sender As System.Object, e As System.EventArgs) Handles Button4.Click

        SP1.PortName = ComboBox1.SelectedItem.ToString
        SP1.BaudRate = 4800
        SP1.BaudRate = 8
        SP1.Parity = Ports.Parity.None
        SP1.StopBits = Ports.StopBits.One
        SP1.Handshake = Ports.Handshake.None
        SP1.Encoding = System.Text.Encoding.UTF8
        Try
            SP1.Open()
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try

        Timer1.Enabled = True
        Button4.Enabled = False
        Label3.Visible = True

    End Sub

    Private Sub SP1_DataReceived(sender As System.Object, e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SP1.DataReceived
        If Me.InvokeRequired() Then
            Dim dr As New DataRecievedDelegate(AddressOf DataRecieved)
            Me.Invoke(dr, e, SP1.ReadByte)
        Else
            DataRecieved(e, SP1.ReadByte)
        End If
    End Sub

    Delegate Sub DataRecievedDelegate(ByVal e As System.IO.Ports.SerialDataReceivedEventArgs, ByVal linka As Integer)

    Sub DataRecieved(ByVal e As System.IO.Ports.SerialDataReceivedEventArgs, ByVal linka As Integer)
        Dim buffer As Integer
        buffer = linka
        TextBox2.Text += buffer & " ; " & odeslany Mod 10 & vbNewLine
    End Sub

    Private Sub Timer1_Tick(sender As System.Object, e As System.EventArgs) Handles Timer1.Tick

        odeslany += 1
        Dim znak(0) As Byte
        znak(0) = odeslany Mod 10
        
        SP1.Write(znak, 0, 1)

        If odeslany >= 10 Then
            Timer1.Enabled = False
        End If
    End Sub
End Class

SP1.BaudRate = 4800 SP1.BaudRate = 8
??

:smiley: moc děkuji