Problemi in ricezione usart

10 Anni 1 Settimana fa #1 da aliasin81
Problemi in ricezione usart è stato creato da aliasin81
Ciao a tutto staff del forum e ringrazio anticipatamente tutti del'eeeeenooooormeeee pazieza :P arrivo al dunque, stavo facendo delle prove per inviare una stringa prelevata dalla funzione sprint e inviarla tramite seriale dal pic 18f45k20 al pic 16f628a facendo il debug con il pic 18 risulta tutto funzionante ora copierò il codice cosi per rendere l'idea:

questa e la stringa da inviare:
sprintf (buffer. "resultato=%+06.2f" resultato) ;

il buffer contiene la stringa.

questa è la funzione che invia i dati tramite seriale:

void uart_read_sprint_string(const unsigned char* buf) {
while((*buf) != '\0')
{
tx_usart(*buf);
buf++;
}
e fino qui con il debug pare tutto ok i dati si trasferiscono nel txreg e partono con la seriale il problema è in ricezione.

Con il pic16 questa è la funzione di ricezione:

//PRENDI DATO DA BUFFER DI RICEZIONE
unsigned char rx_usart(void){

unsigned char rcreg;
//VERIFICA SE DATO E NEL BUFFER DI RICEZIONE
while(PIR1bits.RCIF==0){
}

rcreg=RCREG;



return(rcreg);
}

ma non produce nessun effetto allora ho provato a inviare un numero dal pic18 al pic16 ma fa una strana cosa:
la sequenza è cosi: avvio il sistema il pic16 è collegato ad un display lcd inizializzo e rimane in attesa del dato dopo aver visualizzato dei test di scrittura, il pic18 si avvia allo stesso tempo del pic16 ma gli ho dato un ritardo in modo tale che una volta che il display si setta visualizzando le scritte di prova dopo un pò può ricevere dati dal pic18.A questo punto comincio ha inviare lo stesso dato più volte con un ciclo for per vedere se il display riceve il dato nessuna risposta niente.
Se invece diminuisco questo ritardo sia sul pic18 che sul pic16 fino a farlo quasi a coincidere con la fine dell'inizializzazione del display e la chimata alla funzione di ricezione nel mentre il pic18 gia a inviato un pacchetto su tre dello stesso dato allora il display visualizza il numero che ho inviato e poi comunque come si blocca, è qui che non capisco perchè se chiamo la funzione di ricezione e sta li ad aspettare che arrivi il dato una volta arrivato non fa niente.
Lo so è un po contorta la cosa ma ho cercato di spiegarmi al meglio:
Allora ho optato per l'interrupt questa e la funzione:


void interrupt RX_usart(void){
if (PIR1bits.RCIF==1){ // vedere se interruzione causati da dati in entrata
//CONTROLLA EVENTUALI ERRORI
if(RCSTAbits.FERR==1 || RCSTAbits.OERR==1){
RCSTAbits.CREN=0;
RCSTAbits.CREN=1;
clear_disp();
return_home();
delay_s(1);
dd_ram_number_line(1);
read_string_const(" ERROR USART ");
}


}
prova=RCREG;
}
questa non so se è giusta perchè è la prima volta che uso un int. è in xc8 da come ho capito basta scrivere la funzione intestata:
void interrupt xxxx(void) con il corpo della funzione senza #progma o altro ma non sono sicuro se è giusto, e se fosse cosi l'INT partirebbe da solo non devo chiamare nessuna funzione.Il PIR1bits.RCIF==1 si rileva automaticamente qui sinceramente ho un po di confusione io in tanto continuo a fare delle prove in attesa di qualche delucitazione sicuramente mi sfugge qualche cosa........grazie :blush:

Si prega Accedi o Crea un account a partecipare alla conversazione.

  • aliasin81
  • Junior Member
  • Junior Member
Di più
10 Anni 1 Settimana fa #2 da Mauro Laurenti
Risposta da Mauro Laurenti al topic Problemi in ricezione usart

Rendering Error in layout Message/Item: array_keys(): Argument #1 ($array) must be of type array, null given. Please enable debug mode for more information.

Si prega Accedi o Crea un account a partecipare alla conversazione.

  • Mauro Laurenti
  • Avatar di Mauro Laurenti
  • Moderator
  • Moderator
Di più
10 Anni 6 giorni fa #3 da aliasin81
Risposta da aliasin81 al topic Problemi in ricezione usart
:) ciao mauro grazie dei consigli molto richiesti :blush: ok ho corretto la funzione togliendo il const il collegamento tra i due pic e null modem e per il simulatore io sto usando la scheda prova che mi è stata mandata con il pickit3 poi invierò un file io per fare il debug (pic18f45k20) premo il tasto play accanto hai tasti di programmazione dei pic e del tasto pausa e poi steppo (se si può dire) passo dopo passo il prog e controllo nella finestra dei registri speciali il reg txreg e ho visto che al suo interno scorrono i caratteri generati dalla funzione sprint che sono collocati nell'array di 20 locazioni che io gli ho dichiarato.Per il dispay usando il pic16f628a e non avendo piedini liberi faccio la simulazione virtuale andando sulla proprieta del progetto imposto il simulatore e controllo, poi quando ho finito imposto nuovamente il pickit3 e torna tutto a funzionare in modo normale PS nella simulazione virtuale ancora non ho imparato ad usare gli stimoli :blush: quindi cambio i valori dei registri per far scattare un evento di simulazione, diciamo che preferisco il debug di tipo fisico.Io ho testato cosi ho inserito delle righe di codice sul pic16 per visualizzare su display eventuali errori generati dal flag ferr e oerr e steppando ho notato che quando il pic16 e arriva il primo dato un numero intero mi da errore ferr quindi devo inviare un secondo byte esce dall'errore e visualizza il numero tramite la funzione write_integer ma tra l'invio del primo byte e il secondo io ho dato un attesa di 1 secondo di ritardo ,tolto quello mi da errore di oerr ma questo penso di aver capito perchè almeno credo.Il motivo e che comunque apparte la velocità dei baud 9600 il clock è differente il pic 18 va a 16mhz e il pic16 va a 4mhz quindi i dati inviati saranno trasmessi con un tempo minore della lettura del pic16 che ha un clock più basso quindi devo dare un certo ritardo tra una trasmissione e l'altra per far acquisire e leggere il dato al pic16.Ma per l'errore ferr e come se il byte arrivato avesse qualcosa che non va giusto, ma se la trasmissione è la stessa e la distanza tra i 2 pic si e no e di 10cm perchè fa questo errore? Ed un ultima cosa nella funzione:

void usart_sprint_string( unsigned char* buf) {

while((*buf) != '\0')
{

tx_usart(*buf,2);
}

buf++;

}
ho avuto un po di fortuna perchè il while mi dava errore e allora ho messo tra parentesi per provare (*buf) e li è sparito l'errore, *buf è un puntatore. E il while verifica il suo contenuto e fa il controllo ma tra parentesi cosa cambia non ho capito, e poi se creo un array prova[10] e in una funzione lo chiamo *prova io dovrei cosi avere il contenuto della prima locazione dell'array e volendo potrei incrementarlo cosi prova++ senza utilizzare prova[n]. Questo è un altro piccolo tarlo che ho per capire bene i puntatori.Per la funzione

void usart_sprint_string( unsigned char* buf); devo eliminare il problema del doppio invio per vedere se funziona e poi devo capire se i byte che arrivano è meglio metterli in un array e visualizzarli con la funzione read_string oppure man mano che arrivano usare la funzione read_char per scrivere sul display scrivere i caratteri man mano che arrivano.Grazie di nuovo sto imparando tante cose su questo forum e mi ci voleva :)

Si prega Accedi o Crea un account a partecipare alla conversazione.

  • aliasin81
  • Junior Member
  • Junior Member
Di più
10 Anni 4 giorni fa #4 da aliasin81
Risposta da aliasin81 al topic Problemi in ricezione usart
ciao ha tutti vorrei descrivere i risultati che ho ottenuto non sono molti ma credo di essere a buon punto per quanto riguarda l'errore segnalato dal flag ferr ho notato che avviene solo all'invio del primo dato dopo l'inizializzazione dopo di che sembra che qualsiasi altro dato inviato basta solo una volta ho cercato di eliminare il problema azzerando RCREG all'inizializzazione 2 volte perchè e un doppio buffer per eliminare il problema del flag ferr ma senza sucesso, danno minore a limite una volta che tutte le funzioni funzionino (gioco di parole :P ) faro in modo che all'avvio receva 2 byte per settare il ferr a limite.Per il flag oerr è bastato aggiungere nel mio caso 90ms di ritardo tra una trasmissione e l'altra per evitare di far arrivare troppi dati al ricevitore quando ancore è in lettura del byte già arrivato- E' rimasta ai me il problema più grave l'invio dei caratteri tramite seriale, non capisco se il problema è del ricevitore o del trasmettitore, se il debug è affidabile dal trasmettitore i caratteri partono ho verificato nel registro TXREG che man mano che incrementavo il prog del registro comparivano le lettere della stringa contenuta nel buffer della funzione sprintf e ho aggiunto alla fine anche un doppio carattere di fine stringa '\0' per sicurezza ma sembra che il ricevitore sia come bloccato; perchè come ho detto in precedenza ho aggiunto le seguenti righe nel programma del display:

//PRENDI DATO DA BUFFER DI RICEZIONE
unsigned char rx_usart(void){
unsigned char rcreg;
//VERIFICA SE DATO E NEL BUFFER DI RICEZIONE
while(PIR1bits.RCIF==0){
}
//FERR: Framing Error bit (Lettura)
//se=1 Errore nel frame (viene aggiornato alla lettura del registro di
// ricezione RCREG alla validazione del prossimo byte)
if(RCSTAbits.FERR==1){
clear_disp();
return_home();
dd_ram_number_line(3);
read_string_const(" ERROR USART FERR");

}
// OERR: Overrun Error bit (Lettura)
// se 1=Errore il byte è stato letto ancor prima che fosse ricevuto tutto (può
// essere azzerato dall?azzeramento del bit CREN)
if(RCSTAbits.OERR==1){
clear_disp();
return_home();
dd_ram_number_line(4);
read_string_const(" ERROR USART OERR");
RCSTAbits.CREN=0;
RCSTAbits.CREN=1;
}

rcreg=RCREG;

return(rcreg);

}
in modo tale che se si verificasse qualche errore mi verrebbe scritto sul display invece non compare nessun errore ma neanche si muove questo e il codice prova del display:

/*
* File: Tastiera_LCD.c
* Author: angelo
*
* Created on 9 novembre 2014, 12.39
*/


#include <xc.h>
#include"LCD_MTC-20400X.h"
#include"USART_pic16f628.h"
#include"delay.h"
#define _XTAL_FREQ 4000000

//--setto bit configurazione pic--//
#pragma config FOSC=INTOSCIO
#pragma config WDTE=OFF
#pragma config PWRTE=ON
#pragma config MCLRE=OFF
#pragma config BOREN=OFF
#pragma config LVP=OFF
#pragma config CPD=OFF
#pragma config CP=OFF
//#pragma code high_vector = 0x08
unsigned char prova;
unsigned char prova2;
int invio;
char i=0;
unsigned char buff[20];
void main(void) {
//ABILITAZIONE INTERPT GLOBALE
INTCONbits.GIE=0;
//ABILITAZIONE INTERPT PERIFERICHE
INTCONbits.PEIE=0;
//POWER ON RESET
PCONbits.nPOR=0;
// ABILITATO OSCILLATORE 4MHZ
PCONbits.OSCF=1;
//INIBIZIONE COMPARATORI
CMCON=0x07;
// ASSEGNA PRESCALER A TMR0 E REGOLA RAPPORTO PRESCALER
OPTION_REG=0x07;
// SETTATI SU OUT TRANNE RA5
TRISA=0b00100000;
// SETTA PORTA
PORTA=0;
//SET TRISB 4 OUT E 4 IN
TRISB=0b11111111;
//ABILITA' RESISTORI PULL-UP PORTB
OPTION_REGbits.nRBPU=0;
// AZZERA PORTB
PORTB=0;
//SETTAGIO CLOCK RIARDO IN SECONDI LIBRERIA DRLAY.H
setQuartz (4);
//INIZIALIZE_LCD
inizilization_lcd();
read_string_const("INIZIALIZZAZIONE...");
delay_s(2);
//INIZIALIZAZIONE MODULO USART
open_usart(USART_RX_INT_ON | USART_TX_INT_OFF | USART_ASYNCH_MODE | USART_EIGHT_BIT | USART_CONT_RX | USART_BRGH_HIGH,25);

while(prova!=123){
prova=rx_usart();
dd_ram_number_line(2);
read_string_const("Attesa di ricezione");
}
prova2=rx_usart();
clear_disp();
return_home();

dd_ram_number_line(1);
read_string_const(" LOOK ");

dd_ram_number_line(2);
write_integer_LCD(prova,3);
write_integer_LCD(prova2,3);
dd_ram_number_line(3);
read_string_const(" PROVA STRINGA ");
while(buff=='\0'){
prova=rx_usart();
buff=prova;
i++;
}
dd_ram_number_line(4);
write_char(*buff);
while(1){

}
}

in genere prima dell'arrivo del numero 123 e poi 22 sul display a rotazione velocissimo appare in sequenza
in modo alternato:

attesa di ricezione
ERROR USART FERR
ERROR USART OERR
se è collegato il trasmettitore se invece e scollegato compare:

attesa di ricezione
ERROR USART FERR
in modo fisso

da li capisco che il prog sta girando una volta ricevuto i dati sul display appare cosi

LOOK
123 22
PROVA STRINGA_
il cursore rimane accanto alla scritta che è giusto perchè dovrebbe passare alla 4 riga quando il ciclo while e terminato l'array è pieno e poi scrivere il testo sul display ma prima di ciò si dovrebbe ripetere la seguenza

attesa di ricezione
ERROR USART FERR
ERROR USART OERR
come sopra ma non accade, ora non so se è normale che la faccia perchè in teoria cosi c'è un errore ma quando c'è questa giostra vuol dire che il prog è dentro la funzione di ricezione ora faro una cosa non avendo oscilloscopio ne altri strumenti posso inserire un altro messaggio al di fuori dell'if cosi che anche se non c'è l'errore me lo dirà e cosi capiro che succede intanto metto anche il codice del trasmettitore cosi anche magari per far capire meglio ho dare qualche idea a chi si cimenta con queste cose a presto:

/*
* File: PLC_prova.c
* Author: angelo
*
* Created on 31 ottobre 2014, 13.21
*/


#include<xc.h>
#include <stdio.h>
#include"USART_2_pic18f45k20.h"
#include"delay.h"
//--setto bit configurazione pic--//
#pragma config FOSC=INTIO67
#pragma config WDTEN=OFF
#pragma config PWRT=ON
#pragma config MCLRE=OFF
#pragma config BOREN=OFF
#pragma config LVP=OFF
#pragma config CPD=OFF
#define max_value 30;
unsigned short long c;
unsigned char inc=0;
char i;
//unsigned char a;
unsigned char test;
int b;
unsigned char string[20];
float result;
float A;
//DEFINISCO RB0 COME SWC
#define SWC PORTBbits.RB0
//***inizio programma****//
//ADC Configurazione e comando
//Guardando lo schema del 44-Pin Dimostrativi in Appendice, il potenziometro
//(RP1) uscita è collegata al pin RA0 / AN0 del PIC18F45K20.
//I passaggi di base necessari per convertire la tensione ADC su questo pin sono:
//1 Configurare il pin RA0 / AN0 come un ingresso analogico in ANSEL.
//2 Impostare i riferimenti di tensione ADC in ADCON1.
//3 Impostare la giustificazione risultato, ADC sorgente di clock, e il tempo di acquisizione in ADCON2.
//4 Selezionare il canale e accendere l'ADC in ADCON0.
//5 Avviare la conversione in ADCON0
void main(void){
//OSCINT 16 MZ//
OSCCONbits.IRCF2=1;
OSCCONbits.IRCF1=1;
OSCCONbits.IRCF0=1;
/*PER GARANTIRE UN OTTIMA ACQUISIZIONE E CAMPIONAMENTO BISOGNA AVERE UN TEMPO
MASSIMA 2.25 MICRO SECONDI TUTTO SI BASA SU L'OSCILLATORE USATO QUESTA E LA FORMULA
Fad=FREQUENZA DIVISIONE CLK; OSCHI=OSCILLATORE ESTERNO; FRQA=CALCOLO FREQUENZA CONVERIONE DI OGNI SINGOLO BIT 0.7 MICRO SECONDI PARI 1.6 MICROSECONDI PER TUTTI I 10 BIT
OPPURE 1/0.7= 1.4 MHZ(FRQA) X SINGOLO BIT
Fad=OSCI/FRQA
DOPO DI CHE SI CALCOLA LA FREQUENZA DELLA DIVISIONE DEL CLK; SI USA LA DIVISIONE PIU VICINA AL RISULTATO DEL Fad DIVISO IL RAPPORTO DI OSCIO
TDA=Fad/OSCIO; TAD e Conversion Clock sono la stessa, una espressa in secondi l'altra in Hertz.
TAD = 1/Conversion Clock
VALORE DI ACQUISIZIONE NON MINORE DI 11 MICROSECONDI
"TEMPO DI ACQUISIZIONE DELL'IMPUT CON TAD CIRCA 2.45 MICROSECONDI (tda)"
"TEMPO DI CONVERSIONE CONVERSION CLOCK 1.6 TEMPO MINIMO
USARE FORMULE CHE PIU SI ADDICONO */
//PONGO A 0 REGISTRO LATA//
LATA=0x00;
//SETTO REIGISTRO A TUTTI INPUT COMPRESO RA0 CHE STO UTILIZZANDO //
TRISA=0xff;
LATB=0x00;
TRISB=0xFF;
LATC=0x00;
TRISC=0xff;
//LATD COME OUT//
LATD=0x00;
//TRISD COME OUT//
TRISD=0x00;
LATE=0xff;
TRISE=0x00;
//ABILITO INPUT DIGIT SU RB0//
ANSELHbits.ANS12=0;
//DISABILITO RA0 COME INPUT DIGITALE//
ANSELbits.ANS0=1;
//SETTAGGIO TENSIONE DI RIFERIMENTO SU TENSIONE INTERNA +VCC -VDD//
ADCON1bits.VCFG=0;
ADCON1bits.VCFG0=0;
//SCHELGO IL CANALE DI CONVERSIONE ADC (RA0) SETTO IL FLAG DI START E ACCENDO IL MODULO ADC//
ADCON0=0b00000001;
//SETTO GIUSTIFICAZIONE REGISTRO CONVERSIONE A DESTRA SETTO RITARDO ACQUISIZIONE 20 TDA E IPOSTO FREQUENZA CONVERSIONE SU OSCILLATORE INTERNO//
ADCON2=0b10111111;
//INIZIO CONVERSIONE//
LATD=0x00;
setQuartz (16);
// operazioni//
A=31.0;
result=((A/2.0)-50.0);
//CONVERTI RISULTO IN STRINGA E METTILO IN UN BUFFER//
sprintf(string,"result=%+06.2f",result);
LATDbits.LD0=1;
open_usart(USART_RX_INT_off |USART_TX_INT_off | USART_ASYNCH_mode | USART_EIGHT_bit | USART_CONT_rx | USART_BRGH_hight | USART_BRGH_8_bit,103);
delay_s(4);
for(i=0;i<2;i++){
LATDbits.LD7=1;
tx_usart(123);
LATDbits.LD7=0;
delay_s(1);
}
tx_usart(22);
usart_sprint_string(string);
while(1){
}
}

Si prega Accedi o Crea un account a partecipare alla conversazione.

  • aliasin81
  • Junior Member
  • Junior Member
Di più
9 Anni 11 Mesi fa - 9 Anni 11 Mesi fa #5 da aliasin81
Risposta da aliasin81 al topic Problemi in ricezione usart

Rendering Error in layout Message/Item: array_keys(): Argument #1 ($array) must be of type array, null given. Please enable debug mode for more information.

Si prega Accedi o Crea un account a partecipare alla conversazione.

  • aliasin81
  • Junior Member
  • Junior Member
Di più
Moderatori: Mauro LaurentiPinnaStefAMatteo Garia

Registrati al sito

Accedi a tutte le risorse e articoli non visibili pubblicamente, puoi registrarti con pochi passi.

Registrati al sito LaurTec.

Login