#include "cabecera.
h"
#include <string.h>
#define _XTAL_FREQ 4000000U
#define _I2C_ADDR_LCD 0x4E // 0x7E
#define _START_LINE_2 0xC0
#define _START_LINE_1 0x02
uint8_t nuevoLCD = 0;
uint8_t previoLCD = 1;
char* msj = "000";
unsigned char boton;
uint16_t valorAdc = 0;
uint16_t millar, centena, decena, unidad;
uint16_t cuentaMsjs = 0;
char* canal = "000";
void convierte(uint16_t numero){
millar = numero/1000;
centena = (numero%1000) / 100;
decena = (numero % 100) / 10;
unidad = numero % 10;
return;
}
void configura(void){
// Configuracion de oscilador del sistema a 4MHz ** muy importante para el TIMER1
**
OSCCON1 = 0x60;
OSCFRQ = 0x02;
OSCEN = 0x40;
/* CONFIGURACION DE PUERTOS */
// para el servo
// PWM del CCP1 a traves de RC3
RC2PPS = 0x15;
// elegir con PPS
TRISCbits.TRISC2=1; //Poner como entrada digital
ANSELCbits.ANSELC2=0;
// Configuracion de PWM segun el datasheet (muy importante seguir el orden)
// Timer2: prescaler de 128, Fosc de 4 MHz
// colocar valor calculado en T2PR
T2PR=155;
// CCP1 en modo PWM
[Link]=15;
// siempre limpiar esta bandera tras modificar el modo de captura
PIR3bits.CCP1IF=0;
// Duty cycle formato a la derecha
[Link]=0;
// colocar valor inicial de CCPR1 para ancho de puls
CCPR1 =31;
// limpiar bandera de TMR2IF
PIR3bits.TMR2IF=0;
// Elegir clock source de TMR2 como Fosc/4
[Link] = 1;
// Configurar T2CKPS con el prescaler de 128
[Link] = 7;
// Encender timer con bit T2ON
[Link] = 1;
// encender CCP1
[Link] = 1;
// poner pin RC3 (ver CONFIGURACION DE PUERTOS) como salida digital
TRISCbits.TRISC2=0;
ANSELCbits.ANSELC2=0;
/* CONFIGURACION DE UART1 */
// configuracion de puertos
// Puerto F para usar el UART con los pines del PIC conectados al debugger del
curiosity
// ver datasheet de curiosity:
TRISFbits.TRISF0 = 0; // RF0 como salida digital
ANSELFbits.ANSELF0 = 0;
TRISFbits.TRISF1 = 1; // RF1 como entrada digital
ANSELFbits.ANSELF1 = 0;
U1RXPPS = 0x29; // 00101001 , Pin RF1 para UART RX (UART1) (entrada)
RF0PPS = 0x20; // Pin RF0 para UART TX (UART1) (salida)
// Configuracion de UART1
// BRG = 25 para Fosc 4 MHz y BR de 9600
U1BRGL = 0x19;
[Link] = 0;
[Link] = 1;
// Conf TX
[Link] = 1;
// Conf RX, Config interrupciones
[Link] = 0;
[Link] = 1;
[Link] = 0;
PIE4bits.U1RXIE = 1;
[Link] = 1;
[Link] = 1; // habilita interrupcion por ADC
TRISAbits.TRISA0=1;
ANSELAbits.ANSELA0=1;
[Link] = 1; // justif. derecha
[Link] = 1; // oscilador ADC es ADCRC
ADREF = 0; // Vref+ = Vdd, Vref- = Vss
ADPCH = 0x00; // RA0 como canal elegido
[Link] = 1; // encender ADC
// PUERTO C PARA I2C, para comunicarse con el chip i2c del LCD...
// RC3 SCL, RC4 SDA
// Datasheet: "The SDA and SCL pins must be set as open-drain outputs
TRISCbits.TRISC3 = 0; // outputs
TRISCbits.TRISC4 = 0;
ANSELCbits.ANSELC3 = 0; // digitales
ANSELCbits.ANSELC4 = 0;
ODCONCbits.ODCC3 = 1; // open drain
ODCONCbits.ODCC4 = 1;
// COnfiguracion de PPS para I2C (outputs en RC3, RC4)
RC3PPS = 0x37; // I2C1 SCL
RC4PPS = 0x38; // I2C1 SDA
// Configuracion de puerto C para i2c
[Link] = 2; // RC3I2C, PU = "10". 10x current of standard weak pull-up
[Link] = 1; // RC3I2C, TH = "01". I2C-specific input thresholds
[Link] = 2; // RC4I2C, PU = "10". 10x current of standard weak pull-up
[Link] = 1; // RC4I2C, TH = "01". I2C-specific input thresholds
// CONFIGURACION DE MODULO I2C, para comunicarse con el chip i2c del LCD...
// El datasheet del chip indica que, como maximo, la frecuencia de SCL debe ser 100
KHz, por lo que el clock debera ser MFINTOSC
// El datasheet del chip indica que utiliza direccionamiento i2c de 7 bits
[Link] = 1; // habilitar modulo I2C
[Link] = 3; // MFINTOSC (500 kHz), lo cual genera un SCL a 100 KHz por
defecto
[Link] = 4; // "100", I2C Host mode, 7-bit address
[Link] = 1;
}
void UART1_Data_Send(unsigned char dato){
U1TXB = dato;
while([Link] == 0);
}
void UART1_String_Send(const char *cadena)
{
unsigned char tam;
unsigned char i = 0;
tam = strlen(cadena);
for(i = 0; i<tam; i++)
{
U1TXB = cadena[i];
while([Link] == 0);
}
return;
}
// Funcion para enviar un "numbytes" byte por I2C
uint8_t envia_byte_i2c(uint8_t direccion, uint8_t *dato, uint8_t numbytes){
/*
* "direccion" es un numero de 8 bits que contiene 7 bits de direccion y 1 bit
R/W
* "*dato" es un vector de numeros de 1 byte cada uno
* "numbytes" es la cantidad de valores en el vector
*
El codigo esta hecho para trabajar con la siguiente configuracion de modulo
I2C:
* RC3 SCL, RC4 SDA
* MFINTOSC (500 kHz), lo cual genera un SCL a 100 KHz por defecto
* I2C Host mode, 7-bit address
* Sin uso del registro buffer de address (ADB = 1)
* Todos los demas valores de los registros de configuracion de I2C se dejan
con sus valores por defecto
*/
uint8_t ii = 1;
uint8_t verTXBUFF;
[Link] = 0; // apaga interrupciones para no malograr el flujo de I2C
// ESTO USO CUANDO ADB = 1
I2C1CNT = numbytes;
verTXBUFF = direccion;
I2C1TXB = verTXBUFF; // esto automaticamente manda la condicion START
// primero, el Host (PIC) envia direccion al client y el periferico espera a la
rpta ACK del cliente
while( PIR7bits.I2C1TXIF == 0 ); // Espera a que se haya enviado la direccion
verTXBUFF = dato[0];
I2C1TXB = verTXBUFF; // cargar 1er byte
while(1){
while( [Link] == 1 ); // Espera a recibir la rpta del cliente
(ACK))
if( [Link] == 1 ){
[Link] = 1; // enciende interrupciones antes de salir de la
funcion
return 0;
} // RPTA FUE NACK, terminar COMM
if( I2C1CNT == 0 ){ // Significa que no hay nada mas para enviar,
if ( [Link] == 1 ){
[Link] = 1; // enciende interrupciones antes de salir de
la funcion
return 1;
} // el contador I2C1CNT deberia ser 0, acaba la COMM
}
// Hardware transmite el contenido de I2C1TXB
while( [Link] == 0 ); // espera a que el buffer TX este vacio
if( I2C1CNT == 0 ){ // Significa que no hay nada mas para enviar...
while( [Link] == 0 );// el HW deberia haber enviado STOP
CONDITION, esperar a la condicion y cerrar COMM.
[Link] = 1; // enciende interrupciones antes de salir de la
funcion
return 1;
}
else{ // Significa que hay mas por enviar
while( PIR7bits.I2C1TXIF == 0 ); // Espera a que se haya enviado el
ultimo byte
verTXBUFF = dato[ii];
I2C1TXB = verTXBUFF; // cargar siguiente byte
ii++;
}
}
[Link] = 1; // enciende interrupciones antes de salir de la funcion
return 0;
}
// Funcion para enviar COMANDO al LCD por i2c
uint8_t send_cmd_LCD_i2c(uint8_t cmd)
{
// BITS DEL MODULO I2C-LC2
// D7 D6 D5 D4 x E RW RS
// PARA COMANDOS, el nible INFERIOR debe ser:
// E = 0 o 1
// RW = 0 (write)
// RS = 0
uint8_t data_u, data_l;
uint8_t data_t[4];
data_u = (cmd&0xf0);
data_l = ((cmd<<4)&0xf0);
data_t[0] = data_u|0x0C; //en=1, rs=0
data_t[1] = data_u|0x08; //en=0, rs=0
data_t[2] = data_l|0x0C; //en=1, rs=0
data_t[3] = data_l|0x08; //en=0, rs=0
return envia_byte_i2c(_I2C_ADDR_LCD, data_t, 4);
}
uint8_t send_data_LCD_i2c(char data)
{
// BITS DEL MODULO I2C-LC2
// D7 D6 D5 D4 x E RW RS
// PARA DATOS, el nible INFERIOR debe ser:
// E = 0 o 1
// RW = 0 (write)
// RS = 1
uint8_t data_u, data_l;
uint8_t data_t[4];
data_u = (data&0xf0);
data_l = ((data<<4)&0xf0);
data_t[0] = data_u|0x0D; //en=1, rs=1
data_t[1] = data_u|0x09; //en=0, rs=1
data_t[2] = data_l|0x0D; //en=1, rs=1
data_t[3] = data_l|0x09; //en=0, rs=1
return envia_byte_i2c(_I2C_ADDR_LCD, data_t, 4);
}
// Funcion para inicializar el LCD con i2c
void init_LCD_i2c(void){
// 4 bit initialisation
// 1. Wait for more than 40 mseg
__delay_ms(50);
send_cmd_LCD_i2c(0x30);
__delay_ms(10); // wait for >4.1ms
send_cmd_LCD_i2c(0x30);
__delay_ms(2); // wait for >100us
send_cmd_LCD_i2c(0x30);
__delay_ms(10);
send_cmd_LCD_i2c(0x20); // 4bit mode
__delay_ms(10);
// dislay initialisation
send_cmd_LCD_i2c(0x20); // Function set --> DL=0 (4 bit mode), N = 0 (1 line
display) F = 0 (5x8 characters)
__delay_ms(2);
send_cmd_LCD_i2c (0x08); //Display on/off control --> D=0,C=0, B=0 --->
display off
__delay_ms(2);
send_cmd_LCD_i2c(0x01); // clear display
__delay_ms(2);
send_cmd_LCD_i2c(0x06); //Entry mode set --> I/D = 1 (increment cursor) & S =
0 (no shift)
__delay_ms(2);
send_cmd_LCD_i2c(0x0F); //Display on/off control --> D = 1, C and B = 1.
(Cursor and blink, last two bits)
return;
}
void main(void) {
configura();
[Link] = 1;
init_LCD_i2c();
__delay_ms(1);
send_cmd_LCD_i2c(0x0C);
__delay_ms(1);
send_data_LCD_i2c(0x4D);
__delay_ms(1);
send_data_LCD_i2c(0x69);
__delay_ms(1);
send_data_LCD_i2c(0x63);
__delay_ms(1);
send_data_LCD_i2c(0x72);
__delay_ms(1);
send_data_LCD_i2c(0x6F);
__delay_ms(1);
send_cmd_LCD_i2c(0x14);
__delay_ms(1);
send_data_LCD_i2c(0x44);
__delay_ms(1);
send_data_LCD_i2c(0x44);
__delay_ms(1);
send_cmd_LCD_i2c(0x14);
__delay_ms(1);
send_data_LCD_i2c(0x32);
__delay_ms(1);
send_data_LCD_i2c(0x30);
__delay_ms(1);
send_data_LCD_i2c(0x32);
__delay_ms(1);
send_data_LCD_i2c(0x33);
__delay_ms(1);
send_data_LCD_i2c(0x0B0);
__delay_ms(1);
send_data_LCD_i2c(0x32);
__delay_ms(1);
while(1){
convierte(valorAdc);
if ((valorAdc >= 0) & (valorAdc <= 90)){
CCPR1 =16;
send_cmd_LCD_i2c(0xC0);
__delay_ms(1);
send_data_LCD_i2c(0x30);
__delay_ms(1);
send_data_LCD_i2c(0x30);
__delay_ms(1);
send_data_LCD_i2c(0x30);
__delay_ms(1);
send_data_LCD_i2c(0x25);
__delay_ms(1);
UART1_String_Send("Angulo -90 ");
UART1_Data_Send(10);
UART1_Data_Send(13);
__delay_ms(1000);
else if ((valorAdc > 90) & (valorAdc <= 575)){
CCPR1 =25;
send_cmd_LCD_i2c(0xC0);
__delay_ms(1);
send_data_LCD_i2c(0x30);
__delay_ms(1);
send_data_LCD_i2c(0x31);
__delay_ms(1);
send_data_LCD_i2c(0x34);
__delay_ms(1);
send_data_LCD_i2c(0x25);
__delay_ms(1);
UART1_String_Send("Angulo -67.5 ");
UART1_Data_Send(10);
UART1_Data_Send(13);
__delay_ms(1000);
else if ((valorAdc > 575) & (valorAdc <= 1060)){
CCPR1 =37;
send_cmd_LCD_i2c(0xC0);
__delay_ms(1);
send_data_LCD_i2c(0x30);
__delay_ms(1);
send_data_LCD_i2c(0x32);
__delay_ms(1);
send_data_LCD_i2c(0x38);
__delay_ms(1);
send_data_LCD_i2c(0x25);
__delay_ms(1);
UART1_String_Send("Angulo -45 ");
UART1_Data_Send(10);
UART1_Data_Send(13);
__delay_ms(1000);
}
else if ((valorAdc > 1060) & (valorAdc <= 1545)){
CCPR1 =48;
send_cmd_LCD_i2c(0xC0);
__delay_ms(1);
send_data_LCD_i2c(0x30);
__delay_ms(1);
send_data_LCD_i2c(0x34);
__delay_ms(1);
send_data_LCD_i2c(0x39);
__delay_ms(1);
send_data_LCD_i2c(0x25);
__delay_ms(1);
UART1_String_Send("Angulo -22.5 ");
UART1_Data_Send(10);
UART1_Data_Send(13);
__delay_ms(1000);
else if ((valorAdc > 1545) & (valorAdc <= 2030)){
CCPR1 =56;
send_cmd_LCD_i2c(0xC0);
__delay_ms(1);
send_data_LCD_i2c(0x30);
__delay_ms(1);
send_data_LCD_i2c(0x35);
__delay_ms(1);
send_data_LCD_i2c(0x36);
__delay_ms(1);
send_data_LCD_i2c(0x25);
__delay_ms(1);
UART1_String_Send("Angulo 22.5 ");
UART1_Data_Send(10);
UART1_Data_Send(13);
__delay_ms(1000);
else if ((valorAdc > 2030) & (valorAdc <= 2515)){
CCPR1 =62;
send_cmd_LCD_i2c(0xC0);
__delay_ms(1);
send_data_LCD_i2c(0x30);
__delay_ms(1);
send_data_LCD_i2c(0x37);
__delay_ms(1);
send_data_LCD_i2c(0x30);
__delay_ms(1);
send_data_LCD_i2c(0x25);
__delay_ms(1);
UART1_String_Send("Angulo 45 ");
UART1_Data_Send(10);
UART1_Data_Send(13);
__delay_ms(1000);
else if ((valorAdc > 2515) & (valorAdc <= 3000)){
CCPR1 =71;
send_cmd_LCD_i2c(0xC0);
__delay_ms(1);
send_data_LCD_i2c(0x30);
__delay_ms(1);
send_data_LCD_i2c(0x38);
__delay_ms(1);
send_data_LCD_i2c(0x34);
__delay_ms(1);
send_data_LCD_i2c(0x25);
__delay_ms(1);
UART1_String_Send("Angulo 67.5 ");
UART1_Data_Send(10);
UART1_Data_Send(13);
__delay_ms(1000);
else if ((valorAdc >3000) & (valorAdc <= 4095)){
CCPR1 =80;
send_cmd_LCD_i2c(0xC0);
__delay_ms(1);
send_data_LCD_i2c(0x31);
__delay_ms(1);
send_data_LCD_i2c(0x30);
__delay_ms(1);
send_data_LCD_i2c(0x30);
__delay_ms(1);
send_data_LCD_i2c(0x25);
__delay_ms(1);
UART1_String_Send("Angulo 90");
UART1_Data_Send(10);
UART1_Data_Send(13);
__delay_ms(1000);
}
}
return;
void __interrupt(irq(AD)) ADC_ISR(void)
[Link] = 0;
valorAdc = (uint16_t) ( (ADRESH << 8) | ADRESL); // guarda valor digital en
variable "valorAdc"
[Link] = 1;
return;
void __interrupt(irq(IRQ_U1RX)) U1RX_ISR(void){
PIR4bits.U1RXIF = 0;
LATFbits.LATF3 = ~LATFbits.LATF3;
// POT en RD2, LDR en RD3
if (U1RXB == '1'){
CCPR1 =19;
else if (U1RXB == '2'){
CCPR1 =51;
else if (U1RXB == '3'){
CCPR1 =82;
}
return;
}
void __interrupt(irq(default)) DEFAULT_ISR(void)
{
return;
}