Sari la conținut
ELFORUM - Forumul electronistilor

problema RS232 + buffer soft + USART_UDRE_vect


srdjan

Postări Recomandate

problema e la linia ingrosata unde fac un while ca sa fac expedierea sincrona chiar daca folosesc intrerupere. daca folosesc while-ul respectiv USART_TX_flag nu devine niciodata 0 din ISR. aveti vreo sugestie?

 

definitiile din usart.h

 

#define BAUD 230400UL#define UBRR (((F_CPU/(16*BAUD)))-1)#define CR 0x0d#define LF 0x0a#define BUF_LEN 4volatile unsigned char USART_RX_data[BUF_LEN];volatile unsigned char USART_TX_data[BUF_LEN];volatile unsigned char USART_RX_idx;volatile unsigned char USART_TX_idx;volatile unsigned char USART_TX_flag;

bucati relevante din usart.c

/* * usart.c */#include <avr/io.h>#include <avr/interrupt.h>#include <string.h>#include "usart.h"#include "../cmd/cmd.h"void USART_init(){	USART_RX_idx=0x00;	USART_TX_idx=0x00;	USART_TX_flag=0x00;	UBRRH=(unsigned char)(UBRR>>8);	UBRRL=(unsigned char)UBRR;	UCSRB=(1<<RXCIE)|/*(1<<TXCIE)|(1<<UDRIE)|*/(1<<RXEN)|(1<<TXEN);	UCSRC=(1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);}void USART_output(){	USART_TX_flag=1;	UCSRB|=(1<<UDRIE);[b]	while(USART_TX_flag);[/b]}ISR(USART_UDRE_vect){	if(USART_TX_idx==BUF_LEN)	{		USART_TX_idx=0;		UCSRB&=~(1<<UDRIE);		USART_TX_flag=0;		return;	}	UDR=USART_TX_data[USART_TX_idx];	USART_TX_idx++;}

si apelul din main:

void ANSW_data(uint16_t address, uint16_t value){	USART_TX_data[0]=address>>8;	USART_TX_data[1]=address;	USART_TX_data[2]=address>>8;	USART_TX_data[3]=address;	USART_output();}
Link spre comentariu
  • Răspunsuri 15
  • Creat
  • Ultimul Răspuns

Top autori în acest subiect

  • srdjan

    9

  • nr4

    5

  • mitescu

    1

  • godFather89

    1

Top autori în acest subiect

nu am fost foarte descriptiv in problema.cred ca ceva gresesc eu si nu-mi dau seama unde. variabilele necesare sunt volatile.de ce in ISR(USART_UDRE_vect) setez USART_TX_flag=0 iar in while-ul din USART_output acesta este vazut in continuare ca 1?

Link spre comentariu

Saltul la vectorul de intrerupere se face cand UDR devine empty. In codul expus de tine , toate sunt bune si frumoase , numai ca UDR fiind din start empty, si prin urmare procesul de transmisie nu este declansat, intreruperea nu este generata.

Pentru rezolvare , trebuie sa initializezi o transmisie, dupa care poti intra in bucla while.

exemplu:

void USART_output(){  UDR=USART_TX_data[USART_TX_idx];   USART_TX_idx++;   USART_TX_flag=1;   UCSRB|=(1<<UDRIE);   while(USART_TX_flag);}
Link spre comentariu

imediat dau drumul la sandramaua si o sa mai fac niste teste.

 

de expediat se expediau datele.

 

de exemplu in main apelam

ANSW_data(0xff00, 0x00ff);
si datele ajungeau bine la peer. problema era daca faceam

ANSW_data(0x1111, 0x1111);ANSW_data(0x2222, 0x2222);
la peer ajungeau doar alea cu 0x2222. de aceea vroiam ca USART_output sa stea intr-o bucla pana cand expedierea primului buffer s-a incheiat. Problema era ca acel while devenea infinit si nu intelegeam de ce. Evident ca soltuii viabile am dar nu inteleg in acest caz ce se intampla.
Link spre comentariu

Doar in cazul in care esti sigur ca acolo este problema, poti incerca sa inlocuiesti cu:

do{asm volatile ("nop");}while(USART_TX_flag);
se comporta exact la fel.Am atasat si tot codul sursa asa cum este in momentu de fata (intre experimente).
Link spre comentariu

Din ce mi-am aruncat ochiul prin fisierele din arhiva, iti recomand de inceput ca "sei();" sa-l pozitionezi cel putin inainte de "ANSW_data(0x3131, 0x3030);"Si sper ca e logic motivul.Din aceasta cauza atunci cand nu aveai "while(1)", nu transmitea primele doua cuvinte pentru ca erau suprascrise de urmatoarele.

Link spre comentariu
:) asa este. noroc cu forumul. 4 (6) ochi fac intotdeauna mai mult decat 2. eu intre timp am trecut mai departe prin polling de problema asta. o sa revin la varianta cu intreruperi sa vad daca o lamuresc. desi rusinos, sper ca acesta sa fie baiul. merci mult de interesul aratat.
Link spre comentariu

am facut putin ordine prin cod dar in continuare intampin probleme:

 

eu fac cele 2 apeluri iar rezultatele sunt cum se vede si ma jos, si anume intre cele 2 pachete de date mi se trimit o serie de junk-uri. acum cercetez de ce apar acele junk-uri. poate zariti inaintea mea.

 

LE: am uitat sa resetez contorul.

MLE: asta era :) s-a rezolvat. Multumesc inca o data celor 2 tovarasi.

 

int main(){	LCD_init();	LCD_cursorOff();	USART_init();	CMD_init();	sei();	ANSW_data(0x1234, 0x4321);	ANSW_data(0xabcd, 0xdcba);	while(1)	{		//TODO: if STATE_PLAY or STATE_RQST then process else sleep	}	return 0;}void ANSW_data(uint16_t address, uint16_t value){	USART_TX_data[0]=address>>8;	USART_TX_data[1]=address;	USART_TX_data[2]=value>>8;	USART_TX_data[3]=value;	USART_output();}void USART_output(){	[u]USART_RX_idx=0;[/u]	USART_TX_flag=1;	UCSRB|=(1<<UDRIE);	while(USART_TX_flag);}ISR(USART_UDRE_vect){	UDR=USART_TX_data[USART_TX_idx];	USART_TX_idx++;	if(USART_TX_idx==BUF_LEN)	{		UCSRB&=~(1<<UDRIE);		USART_TX_flag=0x00;	}}12 34 43 21 00 f0 06 01 00 01 00 00 00 00 0d 18  .4C!.ð..........d4 fb 0a d9 60 d5 f3 f9 ed 7d ee 7c ab d3 d6 8c  Ôû.Ù`Õóùí}î|«ÓÖŒfa 2b f0 8a 73 de 60 f8 ff fe 46 d2 3f f6 ff dc  ú+ðŠsÞ`øÿþFÒ?öÿÜ6e dd 99 5f c9 f8 db da e9 e2 63 df f2 fe f5 7f  nÝ™_ÉøÛÚéâcßòþõ6f a7 d7 33 5a fb 53 e1 ec da 4a 7d e8 9c dd 4a  o§×3ZûSáìÚJ}èœÝJ7e bf f6 85 d8 cf fc ee 25 f3 d5 40 f6 8c fb e5  ~¿ö…ØÏüî%óÕ@öŒûå2e d1 c7 3d f8 f0 ec 6e 31 5d 7d 3c 10 cd 4d 79  .ÑÇ=øðìn1]}<.ÍMy71 db 5d 39 7f 2a 8c 95 da a7 c7 a0 29 bb 8e fa  qÛ]9*Œ•Ú§Ç )»Žúf9 4b 60 e0 9b 1b 9c 2d 1c 15 27 fb 62 fd bf e2  ùK`à›.œ-..'ûbý¿â1f fb b1 61 91 5f 0f 5f 32 db f5 0b 49 2d 23 cf  .û±a‘_._2Ûõ.I-#Ïdf 3a 7a f0 2a ec 62 78 bd 07 ac fe b5 25 b5 fe  ß:zð*ìbx½.¬þµ%µþ50 d9 5a f3 67 7f 32 21 b0 f4 7e a1 67 7d 2f f7  PÙZóg2!°ô~¡g}/÷1f f1 7e 6e 1b dc fe bd 8b fb df a6 bf 67 8b 7f  .ñ~n.Üþ½‹ûߦ¿g‹3e 23 7f eb 95 3e ad bc e5 9f ae bf d9 ec ff d6  >#ë•>­¼åŸ®¿ÙìÿÖ43 9e f3 de b6 de 37 6f 1a c1 39 37 75 be 7f b7  CžóÞ¶Þ7o.Á97u¾·2b 7e 5f 4f 7a e2 45 7e b7 90 0d 8d e9 82 77 bf  +~_OzâE~·.é‚w¿ab cd dc ba                                      «Íܺ            
Link spre comentariu

Pe naiba ca tot nu merge cum trebuie. Am atasat din nou arhiva cu sursa completa.deci in apelurile directe catre ANSW_data se trimit ok. Problema e ca dupa ce face un receive pe serial si incearca ulterior un transmit USART_output ramane intr-un ciclu infinit. Am facut in cadrul ciclului un polling (comentat) ca sa iasa totusi din ciclu.Aveti idee ce se intampla sau pur si simplu ma uraste?

Link spre comentariu

chiar la pornire faceam niste ANSW_data ca sa semnalez prezenta pe fir.dupa ce trimit din terminal comanda STOP cand starea e PLAY (la initializare) ar trebui sa raspunda 4 bytes (MSG_OK) folosind ANSW_data. asta nu se mai intampla. dar la initalizare orice trimiteam cu ANSW_data merge bine.Habar n-am ce are.deci practic orice incerc sa raspund cu ANSW_data ca urmare a unei comenzi primite din terminal se bloca la acel while(USART_TX_flag);terminal -> usart.c:80 -> cmd.c:59 -> cmd.c:133 -> cmd.c:184

Link spre comentariu

1. Problema e delicata intr-un fel iar rezolvarea consta in studierea mai amanuntita a "librariei ".2. Iti recomand sa incerci evitarea acestor siruri interminabile de apelari de functii in functii, fara a tine evidenta tipului si atributelor functiilor.Pe scurt poti introduce un "sei()" la inceputul functiei void "USART_output()" ca sa rezolvi repede problema, insa pe parcurs in functie de cum evolueaza programul vor aparea diverse probleme daca nu stapanesti intreruperile, acelasi tip de probleme pe care le-ai intampinat si pana acum.

Link spre comentariu

nu e problema ca folosesc varianta fara intrerupere ca oricum si folosind varianta cu intrerupere tot asteptam sa termine expedierea.e adevarat ca nu am studiat interrupt.h, mie nu mi se parea sa gresesc undeva si de aceea nu intelegeam de ce nu merge.la sugestia 2 nu inteleg concret la ce te referi:la logica programuluila performante datorate overhead-urilor functiilorla urmarirea greoaie a executieimie logica mi se pare simpla. as putea rescrie tot structurat intr-o functie si sa ramana doar macro-urile ISR dar nu cred ca ar conta prea mult la performante iar urmarirea mi se pare simpla.nu iti contest sfatul, dar ca sa-l aplic corect trebuie sa inteleg si de ce :) merci mult.

Link spre comentariu

Creează un cont sau autentifică-te pentru a adăuga comentariu

Trebuie să fi un membru pentru a putea lăsa un comentariu.

Creează un cont

Înregistrează-te pentru un nou cont în comunitatea nostră. Este simplu!

Înregistrează un nou cont

Autentificare

Ai deja un cont? Autentifică-te aici.

Autentifică-te acum



×
×
  • Creează nouă...

Informații Importante

Am plasat cookie-uri pe dispozitivul tău pentru a îmbunătății navigarea pe acest site. Poți modifica setările cookie, altfel considerăm că ești de acord să continui.Termeni de Utilizare si Ghidări