/******************************************************************************
Serial communication library for PIC16F series MCUs.
Compiler: Microchip XC8 v1.12 (http://www.microchip.com/xc)
Version: 1.0 (21 July 2013)
MCU: PIC16F877A
Frequency: 4MHz
NOTICE
NO PART OF THIS WORK CAN BE COPIED, DISTRIBUTED OR PUBLISHED WITHOUT A
WRITTEN PERMISSION FROM EXTREME ELECTRONICS INDIA. THE LIBRARY, NOR ANY PART
OF IT CAN BE USED IN COMMERCIAL APPLICATIONS. IT IS INTENDED TO BE USED FOR
HOBBY, LEARNING AND EDUCATIONAL PURPOSE ONLY. IF YOU WANT TO USE THEM IN
COMMERCIAL APPLICATION PLEASE WRITE TO THE AUTHOR.
WRITTEN BY:
AVINASH GUPTA
me@avinashgupta.com
*******************************************************************************/
#include <stdint.h>
#include <xc.h>
#include "usart_pic16.h"
void USARTInit(void)
{
//Setup queue
UQFront=UQEnd=-1;
//SPBRG
SPBRG=25; //datasheets pagina 76 pic16f628 4MHZ velocidad 2400
//TXSTA
TXSTAbits.TX9=0; //8 bit ttsransmission
TXSTAbits.TXEN=1; //Transmit enable
TXSTAbits.SYNC=0; //Async mode 1= sync 0= async
TXSTAbits.BRGH=0; //High speed baud rate 1= high 0= low
//RCSTA
RCSTAbits.SPEN=1; //Serial port enabled
RCSTAbits.RX9=0; //8 bit mode
RCSTAbits.CREN=1; //Enable receive
RCSTAbits.ADDEN=0; //Disable address detection
//Receive interrupt
RCIE=1;
PEIE=1;
ei();
}
void USARTWriteChar(char ch)
{
while(!PIR1bits.TXIF);
TXREG=ch;
}
void USARTWriteString(const char *str)
{
while(*str!='\0')
{
USARTWriteChar(*str);
str++;
}
}
void USARTWriteLine(const char *str)
{
USARTWriteChar('\r');//CR
USARTWriteChar('\n');//LF
USARTWriteString(str);
}
void USARTHandleRxInt()
{
if(RB1==1)
RB1=0;
else
RB1=1;
//Read the data
char data=RCREG;
//Now add it to q
if(((UQEnd==RECEIVE_BUFF_SIZE-1) && UQFront==0) || ((UQEnd+1)==UQFront))
{
//Q Full
UQFront++;
if(UQFront==RECEIVE_BUFF_SIZE) UQFront=0;
}
if(UQEnd==RECEIVE_BUFF_SIZE-1)
UQEnd=0;
else
UQEnd++;
URBuff[UQEnd]=data;
if(UQFront==-1) UQFront=0;
}
char USARTReadData()
{
char data;
//Check if q is empty
if(UQFront==-1)
return 0;
data=URBuff[UQFront];
if(UQFront==UQEnd)
{
//If single data is left
//So empty q
UQFront=UQEnd=-1;
}
else
{
UQFront++;
if(UQFront==RECEIVE_BUFF_SIZE)
UQFront=0;
}
return data;
}
uint8_t USARTDataAvailable()
{
if(UQFront==-1) return 0;
if(UQFront<UQEnd)
return(UQEnd-UQFront+1);
else if(UQFront>UQEnd)
return (RECEIVE_BUFF_SIZE-UQFront+UQEnd+1);
else
return 1;
}
void USARTWriteInt(int16_t val, int8_t field_length)
{
char str[5]={0,0,0,0,0};
int8_t i=4,j=0;
//Handle negative integers
if(val<0)
{
USARTWriteChar('-'); //Write Negative sign
val=val*-1; //convert to positive
}
else
{
USARTWriteChar(' ');
}
if(val==0 && field_length<1)
{
USARTWriteChar('0');
return;
}
while(val)
{
str[i]=val%10;
val=val/10;
i--;
}
if(field_length==-1)
while(str[j]==0) j++;
else
j=5-field_length;
for(i=j;i<5;i++)
{
USARTWriteChar('0'+str[i]);
}
}
void USARTGotoNewLine()
{
USARTWriteChar('\r');//CR
USARTWriteChar('\n');//LF
}
void USARTReadBuffer(char *buff,uint16_t len)
{
uint16_t i;
for(i=0;i<len;i++)
{
buff[i]=USARTReadData();
}
}
void USARTFlushBuffer()
{
while(USARTDataAvailable()>0)
{
USARTReadData();
}
}
/******************************************************************************
Serial communication library for PIC16F series MCUs.
Compiler: Microchip XC8 v1.12 (http://www.microchip.com/xc)
MCU: PIC16F877A
Frequency: 4MHz
NOTICE
NO PART OF THIS WORK CAN BE COPIED, DISTRIBUTED OR PUBLISHED WITHOUT A
WRITTEN PERMISSION FROM EXTREME ELECTRONICS INDIA. THE LIBRARY, NOR ANY PART
OF IT CAN BE USED IN COMMERCIAL APPLICATIONS. IT IS INTENDED TO BE USED FOR
HOBBY, LEARNING AND EDUCATIONAL PURPOSE ONLY. IF YOU WANT TO USE THEM IN
COMMERCIAL APPLICATION PLEASE WRITE TO THE AUTHOR.
WRITTEN BY:
AVINASH GUPTA
me@avinashgupta.com
*******************************************************************************/
#ifndef USART_PIC16_H
#define USART_PIC16_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
//Constants
#define RECEIVE_BUFF_SIZE 32
//Variables
volatile char URBuff[RECEIVE_BUFF_SIZE]; //USART Receive Buffer
volatile int8_t UQFront;
volatile int8_t UQEnd;
void USARTInit(void);
void USARTWriteChar(char ch);
void USARTWriteString(const char *str);
void USARTWriteLine(const char *str);
void USARTWriteInt(int16_t val, int8_t field_length);
void USARTHandleRxInt();
char USARTReadData();
uint8_t USARTDataAvailable();
void USARTGotoNewLine();
void USARTReadBuffer(char *buff,uint16_t len);
void USARTFlushBuffer();
#ifdef __cplusplus
}
#endif
#endif /* USART_PIC16_H */
#define _XTAL_FREQ 4000000
#include <xc.h>
#include <pic16f628a.h>
#include <stdio.h>
#include <stdlib.h>
#include "confbits.h"
#include <string.h>
#include "711.h"
#include "usart_pic16.h"
//**************************** variables globales
//**************************************************************************
void main(void)
{
// **********************inicializo el micro
// ******************** inicializacion cpu ***************************
PCONbits.OSCF;// reloj en 4 mhz
CMCON = 0X07 ; //apaga los comparadores y habilita los pines de I/O
TRISA = 0x00;
PORTA = 0X00;
TRISBbits.TRISB1 = 1; //terminal rx como entrada
TRISBbits.TRISB2 = 0; //terminal tx como salida
TRISBbits.TRISB5 = 0; // adsk como salida
TRISBbits.TRISB3 = 1; // add0 como entrada
TRISBbits.TRISB4 = 0; // salida relay
USARTInit();
unsigned long datos ;
unsigned char salida[7];
unsigned char *ptr, i,datas;
while (1)
{
uint8_t n = USARTDataAvailable();
if (n != 0)
{
datas = USARTReadData();
USARTWriteChar(datas);
PORTBbits.RB4 = 1;
__delay_ms(100);
}
PORTBbits.RB4 = 0;
// datos = ReadCount();
// ptr = &datos; // puntero apunta a la direccion de 8 bits donde se encuentra el dato
// sprintf(salida,",%02X%02X%02X",*(ptr+2),*(ptr+1),*ptr); //suma 1 y 2 al puntero 8 16 y 24 bits
// USARTWriteString(salida); // transmito los 24 bits completos en Hexa
}
// PIC16F648A Configuration Bit Settings
// 'C' source line config statements
#include <xc.h>
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
// CONFIG
#pragma config FOSC = INTOSCCLK // Oscillator Selection bits (INTOSC oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = OFF // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital input, MCLR internally tied to VDD)
#pragma config BOREN = ON // Brown-out Detect Enable bit (BOD disabled)
#pragma config LVP = OFF // Low-Voltage Programming Enable bit (RB4/PGM pin has PGM function, low-voltage programming enabled)
#pragma config CPD = OFF // Data EE Memory Code Protection bit (Data memory code protection off)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
//__CONFIG(FOSC_INTOSCIO & WDTE_OFF & PWRTE_ON & MCLRE_OFF & BOREN_ON & LVP_OFF & CPD_OFF & CP_OFF);
Tu problema es que no estas usando las interrupciones...
Te explico, tu codigo crea un buffer circular, el cual cuando recibe un dato lo guarda en ese buffer, el tema es que UARTdataRead o como se llame, lee del buffer y no la entrda. Igual que la otra funcion que usaste indicando si hay datos disponibles. se f ija si el buffer contiene algo.. Pero... ¿quien llena ese buffer? Veamos eso...
En tu UARTInit:Código: C
//Receive interrupt RCIE=1; PEIE=1; ei(); }
Se activan las interrupciones.. eso quiere decir que con las interrupciones tenemos que hacer algo.. deberiamos crear una por nosotros mismo y que vaya llenando el buffer? No.. ya esta realizado:Código: C
void USARTHandleRxInt()
Asi que en tu main. o cualquier otro arhivo que tengas para todas las interrupciones, deberias hacer algo asi:Código: C
void interrupt RX_INT (void) { USARTHandleRxInt(); }
De esa forma el Handler se encarga de cuando entra a una interrupcion de llenar ese buffer circular y avanzar los indices.
Creo que es lo unico que te falla
Mil disculpas KILLERJC ...me olvide de postear la interrupt ....pero la tengo escrita ....ya funciona ...
ahora el tema es que mientras estoy saliendo por tx , me deberia recibir el caracter por RX ...y lo recibe, pero desp de insistir ...es como que mientras esta transmitiendo no se activa la interrup ...o algo asi
Gracias
saludos
PORTBbits.RB4 = 0;
while (1)
{
uint8_t n = USARTDataAvailable();
if (n != 0)
{
datas = USARTReadData();
if (datas == 'D') // DISPARO
{
PORTBbits.RB4 = 1;
}
else if (datas == 'C') // CORTE
{
PORTBbits.RB4 = 0;
}
}
datos = ReadCount();
ptr = &datos; // puntero apunta a la direccion de 8 bits donde se encuentra el dato
sprintf(salida,",%02X%02X%02X",*(ptr+2),*(ptr+1),*ptr); //suma 1 y 2 al puntero 8 16 y 24 bits
USARTWriteString(salida); // transmito los 24 bits completos en Hexa
}
}Mil disculpas KILLERJC ...me olvide de postear la interrupt ....pero la tengo escrita ....ya funciona ...
ahora el tema es que mientras estoy saliendo por tx , me deberia recibir el caracter por RX ...y lo recibe, pero desp de insistir ...es como que mientras esta transmitiendo no se activa la interrup ...o algo asi
Gracias
saludos
Solamente estas probando esto no ?:Código: C
if (USARTDataAvailable()) { datas = USARTReadData(); USARTWriteChar(datas); PORTBbits.RB4 ^= 1; __delay_ms(100); }
Si es solo eso.. quitale el delay y probalo. o usa
void USARTReadBuffer(char *buff,uint16_t len);
y
void USARTWriteString(const char *str);
Sino estas leyendo caracter por caracter, y la transmision es bloqueante
Si probas, quitale el sprint y lo demas... solamente deja la parte de arriba, asi vemos que parte es el problema. Me refiero a dejar esta parte de codigo:Código: C
if (USARTDataAvailable()) { datas = USARTReadData(); if (datas == 'D') // DISPARO { PORTBbits.RB4 = 1; } else if (datas == 'C') // CORTE { PORTBbits.RB4 = 0; } }
Tambien prodrias probar poner que cada ves que entre a la interrupcion cambie el estado de otro pin suponete RB3 y te aseguras que si o si se recibio correctamente.Código: C
void interrupt INTs (void) { if(PIR1bits.RCIF && PIE1bits.RCIE) USARTHandleRxInt(); PORTBbits.RB3 ^= 1; }
Si probas, quitale el sprint y lo demas... solamente deja la parte de arriba, asi vemos que parte es el problema. Me refiero a dejar esta parte de codigo:Código: C
if (USARTDataAvailable()) { datas = USARTReadData(); if (datas == 'D') // DISPARO { PORTBbits.RB4 = 1; } else if (datas == 'C') // CORTE { PORTBbits.RB4 = 0; } }
Tambien prodrias probar poner que cada ves que entre a la interrupcion cambie el estado de otro pin suponete RB3 y te aseguras que si o si se recibio correctamente.Código: C
void interrupt INTs (void) { if(PIR1bits.RCIF && PIE1bits.RCIE) USARTHandleRxInt(); PORTBbits.RB3 ^= 1; }
EDIT:
No hagas caso a lo ultimo que dije lo de la salida, veo que ya el Handler maneja el RB1