Hledám zdrojový kód v C pro nastavení USART na ATmega8

este sa chcem spytat. Ak by som chcel pouzit interny oscilator pre usart, tak ako by som mal najlepsie nastavit frekvenciu a baud rate aby to slapalo?

Nastavovanie postiek(fuses) , kuk stranku.

no uz som prisiel na to. potrebujem nastavit interny oscilator na 8MHz, pri baud rate 9600 UBRR=51, ako nastavit tie bity ? :slight_smile:

no tak z datasheetu: CKSEL 3…0=0100 (8MHz), SUT 1…0=10 (65ms), len neviem co s OSCCAL bo to tam je v percentach a hodnoty 0x00, 0x7F, 0xFF, a najvacsi problem ako to napisat v kode :slight_smile:

#include <avr/io.h>
#include <inttypes.h>

void USARTInit(uint16_t ubrr_value)
{

UBRRL = ubrr_value;
UBRRH = (ubrr_value>>8);
UCSRC=(1<<URSEL)|(3<<UCSZ0);
UCSRB=(1<<RXEN)|(1<<TXEN);

}

char USARTReadChar()
{

while(!(UCSRA & (1<<RXC)))
{

}
return UDR;

}

void USARTWriteChar(char data)
{
while(!(UCSRA & (1<<UDRE)))
{

}
UDR=data;

}

void main()
{

char data;

USARTInit(51);		//UBRR = 51

while(1)
{
	data=USARTReadChar();


	USARTWriteChar('');
	USARTWriteChar(data);
	USARTWriteChar(']');
}

}

kde do kodu mam definovat CKSEL, SUT a OSCCAL? a aku hodnotu priradit OSCCAL ? som to nepochopil v tom datasheete

OSCCAL=0xE4 mi zobralo ale ked dam CKSEL3=0 tak napise ze nie je deklarovanane a ani SUT

Fuses nastavujes pomocou programatora.
Tak ako posielas do mcu kod, tak tvoj programator musi mat moznost prepisat Fuses i OSCCAL (Dragon umoznuje OSCCAL programovat samostatne).
Fuses sa neprepisuju “v ramci programu”, ale pomocou programatora.

Tak som sa rozhodol ze pouzijem externy krystal 7,3728 MHz Baud rate 9600, UBRR=47,(dufam ze je to spravne) pripojil som ho na mega8 na 9 a 10 pin (XTAL1, XTAL2) plus na obidve nozisky som dal 22pF kondiky ktore idu na zem ,v avr studio som v nastaveniach fuses nastavil na Externy crystal -high freq.-65ms [CKSEL1111, SUT11] a este CKOPT=1 (to som nasiel aj v datasheete). a zrazu sa nemozem dostat na megu ani zapis nic, resp. je odpalena a neviem v com mohol nastat problem. Nezabudol som na nieco? pripojil som aj pic kde su nastavenia z datasheetu.
A este ked som nsatavil interny oscilator na 8Mhz tak som aspon komunikoval cez hyperterminal lenze mi to nehadzalo tie hodnoty ktore malo, tak neviem kto by mi poradil co s tym… :unamused:

Skus pozriet moj prispevok z 04 březen 2009, 20:14.
Asi si si Fuses nastavil presne opacne ako si chcel (napr. v Ponyprogu zaskrtnute uses znamena nastavenie do 0, neviem aky program pouzivas).
Procesor teraz caka, kedy ze mu to pride z vonku frekvencia, aby sa mohol podla nej riadit (pozdri v datasheete mod “vsetky prislusne fuses na nulu”).
Pomoze tam tu frekvenciu dodat, napr z ineho procesora, ktory moze kmitat nazickou, alebo z generatora napr. s 555. Na stabilite a presnosti frekvencie nezalezi, ale frekvencia musi byt aspon 4x vyssia ako je programovacia frekvencia cez SPI.
Ale na to postvy paralelny programator. Ten si s tym vie rady vzdy.
V ziadnom pripade sa nejedna o nejaku chybu, ci uz programatora, alebo procesora.
Jednoducho, ak ma procesor moznost nastavit rozne zdroje hodin, tak ich musi byt samozrejme mozne i nejak prenastavit a ak si obsluha vyberie kombinaciu, ktoru jej hw neobsahuje, procesor sa to uz nema ako dozvediet a pracuje podla nastavenych fuses (poistiek). Treba vediet co sa robi a ako (polarita poistiek v obsluznom programe)
Ale procesor rozhodne vyhadzovat nemusis :slight_smile:

No tak seriovu linku som uz rozbehal, len mojim dalsim problemom je nastavit casovanie! chcel by som to nastavit na 1ms, pouzivam krystal 7,3728 Mhz, v datasheete som sa docital: treba si zvolit predelicku (8,64,256,1024), z mojej frekvenice potrebujem dostat cas (1/f), tento cas vynasobit tak aby som dostal cca tu 1ms. pri 8bit max 255, , 1ms podelit casom=1/f … a uz sa stracam a ani neviem co som pisal poriadne… vie mi to nekto vysvetlit respektive vypocitat?

Kmitočet krystalu f = 7,3728 MHz.
1 perioda = 1 / f = 1 / 7,3728 = 0,13563 microsec.

1 krok čítače trvá 0,13563 microsec.

Pro 1000 us potřebujeme
1000 / 0,13563 = 7328 kroků.

Pro osmibitový čítač použijeme dělič 64.
Počet kroků je pak 7328 / 64 = 115,2.
Když nastavíme 115, chyba bude 1,7 promile.

dik zxa info, len 1000/0,13563 je myslim 7373 :wink: a este k tej predelicke tu si volim tak aby som mal co najmensie desatine cislo ak som dobre pochopil ?

Ano, má být 7373.

Předděličku použijeme tehdy, když počet kroků vyjde větší, než je rozsah čítače, který chceme použít.

Timer1 má max hodnotu 65535, takže pro 7373 kroků není třeba předděličky.

Ale např. pro 10 ms vyjde 73730 kroků, takže použijeme předdělič /stačí 8/.
Prostě použít co nejmenší předděličku, aby se žádaný počet kroků vešel do 16 bitů (nebo do osmi bitů u osmibitového čítače).

Skor 1.7 percenta :wink:

Ja to riesim tak, ze si pocitam pocet preruseni a kazde piate nastavim na 116.
(pre predvolbu 115 treba nastavit do OCR cislo 114 a pre predvolbu 116, cislo 115)
Tym vznikne presny deliaci pomer 115.2 v 2.5 ms. Aby to bolo v 2.5ms, prerusenie generujem kazdych 500us.
Ale chyba vznika v tej frekvencii Xtalu, lebo ta nie je 7.3730MHz, ale 7.3728MHz.
co je 0.0027%. Myslim, ze je pre bezne pouzitie uplne zanedbatelna.

no ak to chcem vsetko nastavit v kode ? :slight_smile: rozhodol som sa pre timer/counter1 (16bit) aby som nemusel pouzit predelicku. Ale co vsetko nastavit? alebo treba pouzit nejaky rezim (CTC,PWM…??), jedine co vime tak nastavit timer: TCCR1B|=(1<<CS10); potom ho checknut: if (TCNT1>=7373) … TCNT1=0; (reset) a dalej neviem ako nastavit reg. TIMSK(maskovanie prerusenia), TIFR(nastavenie priznaku)…

[code]
// pre cnt2

#define T2_CNT TCNT2
#define T2_PREDVOLBA OCR2A
#define POCET_PRVEJ_PREDVOLBY 5 // pocet priradenia hodnoty TB_DEFAULT_1 a TB_DEFAULT_2 do komparacneho registra
#define TB_DEFAULT_1 229 //230-1 pouzije sa POCET_PRVEJ_PREDVOLBY, alebo 115-1, ak mas pomalsi Xtal
#define TB_DEFAULT_2 231 //232-1 pouzije sa 1x, (ak POCET_PRVEJ_PREDVOLBY = 5, potom bude priemer 230.4) , alebo 116-1, ak mas pomalsi Xtal, potom bude priemer 115.2

uint8_t tb_cnt_count_int_tb = POCET_PRVEJ_PREDVOLBY;

// inicializacna cast

void cnt_ini(void)
{
TCCR2A = (1<<WGM21);
TCCR2B = (1<<CS22);
SET(TIMSK2,OCIE2A); // povolenie interuptu pri compare match
}

ISR(SIG_OUTPUT_COMPARE2A)
{

if (--tb_cnt_count_int_tb) {  // najprv sa dekrementuje pocitadlo vlozenia predvolieb a potom sa porovna
	TB_PREDVOLBA = TB_DEFAULT_1; 
}
else {
	tb_cnt_count_int_tb = POCET_PRVEJ_PREDVOLBY;
	TB_PREDVOLBA = TB_DEFAULT_2;
}

// … tu si daj co chces
// je to napisane narychlo, dufam, ze tam nebudu nejake neprekonatelne chyby
}[/code]

tak s timerom1 som si poradil :slight_smile: moja funkcia:

void Init_Timer(void)
{
//nastavenie timer1 pre CTC mod
TCCR1B |= (1 << WGM12);

//povolit CTC interrupt
TIMSK |= (1 << OCIE1A);

//nastavit CTC porovnavaciu hodnotu pri 7,3728MHz AVR-clock

//OCR1A = 9216; //pre 10ms
OCR1A = 7200; //pre 1s

//start timer

//TCCR1B |= (1 << CS11); //pre fcpu/8
TCCR1B |= (1 << CS12) | (1 << CS10); //pre fcpu/1024
}

potom main:
int main(void)
{

USARTInit(95);		//UBRR = 95 pre 7,3728 MHz external crystal

ak U2X=1
Init_Timer();

while(1)
{
	if (TIFR & (1 << OCF1A))
	{
		USARTWriteChar('P');
		TIFR = (1 << OCF1A);
	}	
}

}

ide to ako ma len ked chcem napriklad vypisovat kazdych 30sekund tak uz dostavam velku hodnotu ktora sa mi neznesti do 16bit timera.

30s=30 000ms=30 000 000 us,
pri predelicke max 1024 je hodnota OCR1A = 216 000 co je viac ako 65tis nieco, tak neviem ako sa tu teraz postupuje…

   if (--tb_cnt_count_int_tb) {  // najprv sa dekrementuje pocitadlo vlozenia predvolieb a potom sa porovna
      TB_PREDVOLBA = TB_DEFAULT_1;
   }
   else {
      tb_cnt_count_int_tb = POCET_PRVEJ_PREDVOLBY;
      TB_PREDVOLBA = TB_DEFAULT_2;
   }

presne tak, ako som Ti napisal … rozsirenie 8b je 16b, pouzi pre rozsirenie 16b na 24b

pouzil som funckciu case (switch) a av avr studiu ako by to nepoznalo; hlasi chybu:
…/usart_new.c:127: error: expected declaration or statement at end of input
make: *** [usart_new.o] Error 1

pouzivam len:
#include <avr/io.h>
#include <inttypes.h>
#include <avr/interrupt.h>
#include “uart.h”

Zdravim,
poradil by mi nekdo kde je chyba v následujícím kódu? Melo by to jen načíst znak z klávesnice a poslat ho zpět… Díky
V hyperterminálu nastavuju rychlost 9600, datové bity 8, parita žádná, stop bit 1, řízení toku žádné

#include <avr/io.h>
#include <stdlib.h>
#include <util/delay.h>
#include <stdio.h>

#define MYUBRR 51

void USART_Init( unsigned int ubrr)
{
/* Set baud rate /
UBRRH = (unsigned char)(ubrr>>8);
UBRRL = (unsigned char)ubrr;
/
Enable receiver and transmitter /
UCSRB|=0x18;
/
Set frame format: 8data, 1stop bit */
UCSRC |=0x86;
}

void main( void )
{
char znak;

USART_Init ( MYUBRR );

while(1) {
znak=getchar();
putchar(znak);
}

}