#include "xc.h"
#include <stdint.h>
#include <stdbool.h>
#include <uart.h>
#define FCY 16000000UL
void Configuracion_Oscilador(void);
void Configuracion_Pines(void);
void Configuracion_UARTs(void);
char * utoa(char * buf, unsigned val, int base);
uint32_t contador1 = 0;
uint32_t contador2 = 0;
extern uint8_t algo;
char resultado[10];
int main(void)
{
Configuracion_Pines();
Configuracion_Oscilador();
Configuracion_UARTs();
// Deshabilito las interrupcion nesteadas
_NSTDIS = 1;
// 4 escrituras. Ya que la interrupcion se realiza cuando 3/4 lleno el buffer
WriteUART1(++contador1);
WriteUART2(++contador2);
WriteUART1(++contador1);
WriteUART2(++contador2);
WriteUART1(++contador1);
WriteUART2(++contador2);
WriteUART1(++contador1);
WriteUART2(++contador2);
while(1)
{
_LATB0 = ~ _LATB0;
__delay32(8000000);
if(algo != 0)
{
if(contador1>contador2)
{
utoa(resultado,(contador1-contador2),10);
}
else
{
utoa(resultado,(contador2-contador1),10);
}
putsUART1((unsigned int *)"Diferencia contadores:");
putsUART1((unsigned int *)resultado);
putsUART1((unsigned int *)"\n\r");
}
}
return 0;
}
void Configuracion_Oscilador(void)
{
/*
* 8Mhz cristal externo , entrada de frecuencia se cumple 0.8Mhz 8.0Mhz
* Fin * M/N1 = Fvco = 128Mhz tambien se cumple , 120 a 340 Mhz
* Fosc = Fvco / N2 = 32Mhz cumple con lo establecido, 15 a 120Mhz
* Fp = Fosc / 2 = 16Mhz
*/
PLLFBD = 30; // M = 32
_PLLPOST = 0; // N1 = 2 (default)
_PLLPRE = 1; // N2 = 4 (default)
__builtin_write_OSCCONH(0x03); // Nuevo oscilador en Oscilador Principal con PLL
__builtin_write_OSCCONL(OSCCON | 0x01); // Activo el bit para el cambio de oscilador
// Esperamos el cambio de clock, es decir cuando el oscilador actual pase a ser PRIOSC + PLL
while (_COSC != 0b011);
// Esperamos al PLL que se enganche
while (_LOCK != 1);
// No se si es necesario para hacer que la CPU realmente funcione a 1:1 con Fp
_ROI = 1;
}
void Configuracion_Pines(void)
{
_TRISB0 = 0;
_LATB0 = 0;
}
void Configuracion_UARTs(void)
{
uint16_t baudvalue;
uint16_t UMODEvalue;
uint16_t USTAvalue;
CloseUART1(); // Solo por si acaso fue un reset
CloseUART2();
/*
* Configuracion de las interrupciones, habilitadas/deshabilitadas
* y prioridades de las mismas
*/
ConfigIntUART1(UART_RX_INT_EN & UART_RX_INT_PR6 &
UART_TX_INT_DIS);
ConfigIntUART2(UART_RX_INT_EN & UART_RX_INT_PR6 &
UART_TX_INT_DIS);
/*
* Configuracion de la UART,
*
* UxMODE Register:
* UART_EN : UART habilitada
* UART_IDLE_CON : Modo de operacion continua en Idle
* UART_DIS_WAKE : Deshabilitado el Wake-Up por medio de la UART
* UART_EN_LOOPBACK: habilito el Loopback
* UART_DIS_ABAUD : Deshabilitado el Auto-Baud
* UART_NO_PAR_8bit : Sin paridad y 8 bits
* UART_1STOPBIT : 1 bit de stop
* UART_IrDA_DISABLE: Desativa la codificacion IrDA
* UART_UEN_00 : Pines RX y TX usados por el modulo, los demas ( CTS,RTS por el usuario )
* UART_BRGH_SIXTEEN : High Baud Rate Generator desactivado
* UART_MODE_SIMPLEX : Modo Simple sin control de Flujo
*
* UxSTA Register:
* UART_INT_TX_BUF_EMPTY : Interrupcion generado cuando se vacia el buffer
* UART_IrDA_POL_INV_ZERO : Idle state la salida esta en 0 (al no estar habilitado IrDA se refiere a UxTX )
* UART_TX_ENABLE : Activamos el Transmisor
* UART_INT_RX_3_4_FULL : Definimos que el flag se ponga a 1 a los 3/4 del buffer
* UART_ADR_DETECT_DIS: Deshabilitamos la deteccion de direccion ( aunque con 8 bits no funciona )
* UART_RX_OVERRUN_CLEAR : Limpiamos el bit de Overrun por si las dudas
*/
UMODEvalue = UART_EN & UART_IDLE_CON &
UART_DIS_WAKE & UART_EN_LOOPBACK &
UART_DIS_ABAUD & UART_NO_PAR_8BIT &
UART_1STOPBIT & UART_IrDA_DISABLE &
UART_UEN_00 & UART_BRGH_SIXTEEN &
UART_MODE_SIMPLEX;
USTAvalue = UART_INT_TX_BUF_EMPTY & UART_IrDA_POL_INV_ZERO &
UART_TX_ENABLE & UART_INT_RX_3_4_FUL &
UART_ADR_DETECT_DIS & UART_RX_OVERRUN_CLEAR;
/*
* Baud = 16Mhz / ( 16 * (baudvalue + 1) ) = 58523
* Error % = (58523 - 57600) / 57600 = 0.2124 %
*/
baudvalue = 16;
OpenUART1(UMODEvalue,USTAvalue,baudvalue);
OpenUART2(UMODEvalue,USTAvalue,baudvalue);
}
char * utoa(char * buf, unsigned val, int base)
{
unsigned v;
char c;
v = val;
do {
v /= base;
buf++;
} while(v != 0);
*buf-- = 0;
do {
c = val % base;
val /= base;
if(c >= 10)
c += 'A'-'0'-10;
c += '0';
*buf-- = c;
} while(val != 0);
return ++buf;
}