220 likes | 336 Views
PIC 16F873 CONVERSIÓN A/D Y TRANSMISIÓN POR PUERTO SERIE. PSP: Adolfo Murrieta González. OBJETIVOS. Utilizar PIC para la adquisición de datos analógicos y conversión a digital Transmisión por puerto serie de los datos Posterior análisis de datos en el PC. MEDIOS A UTILIZAR.
E N D
PIC 16F873CONVERSIÓN A/D Y TRANSMISIÓN POR PUERTO SERIE • PSP: Adolfo Murrieta González
OBJETIVOS • Utilizar PIC para la adquisición de datos analógicos y conversión a digital • Transmisión por puerto serie de los datos • Posterior análisis de datos en el PC
MEDIOS A UTILIZAR • Microchip 16F873 • convertidor A/D • controlador Puerto Serie • PCB diseñado para alojar el 16F873 y módulos requeridos • código diseñado para conseguir los objetivos, PC y conexiones
PIC 16F873 • CPU RISC • juego de 35 instrucciones • 28 pins • FLASH: 8K x 14 words • RAM: 368 x 8 bytes • EEPROM: 256 x 8 bytes • Conversor A/D de 10 bits multicanal • Puerto Serie multifuncional
PIC 16F873 - Conversor A/D • Hasta 5 canales de entrada • Conversión por método de aproximaciones sucesivas • 10 bits de resolución • Voltaje alto y bajo de referencia seleccionable por software • Posibilidad de ejecución en modo SLEEP
PIC 16F873 - Conversor A/D • 4 registros básicos: • 2 registros configuración: • ADCON0 • ADCON1 • 2 registros datos: ADRESH y ADRESL
PIC 16F873 - Conversor A/D • ADQUISICION DE DATOS: • 1) Programación del conversor A/D: • Programar Frecuencia de Adquisición (ADCON0 - bits ADCS0 y ADCS1): Fosc/2 (00) Fosc/8 (01) Fosc/32 (10) FRC (11) • Seleccionar canal de entrada (ADCON0 - bits CHS0, CHS1, CHS2) • Canal 0 (000) ... Canal 7 (111)
PIC 16F873 - Conversor A/D • Configurar Pines, voltaje referencia, ... (ADCON1 - bits PCFG0, PCFG1, PCFG2, PCFG3): • Configurar bit de Resultado (ADCON1 - bit ADFM ) • Habilitar el modulo conversor (ADCON0 - bit ADON )
PIC 16F873 - Conversor A/D • 2) Para cada dato a adquirir: • Empezar la conversion (ADCON0 - bit GO-DONE) • Comprobar la conversion: • por polling (comprobar ADCON0 - bit GO-DONE)
PIC 16F873 - Interfaz Serie • Posibilidad de configuración para comunicación: • full-duplex asíncrona. • Sincrona como Master • Síncrona como Slave • Utilizaremos el modo asíncrono
PIC 16F873 - Interfaz Serie • MODO ASINCRONO: • codificación standard NRZ • formato standard de 8 bits ( configurable ) • se transmite primero el bit LSB • paridad no soportada por HW pero puede calcularse por SW y almacenarse en bit 9
PIC 16F873 - Interfaz Serie DIAGRAMA DEL BLOQUE DE TRANSMISION
PIC 16F873 - Interfaz Serie • PROGRAMACION: • 1) Inicializar registro del Generador de baudios (SPBRG) y el bit de alta velocidad si necesario (BRGH)
PIC 16F873 - Interfaz Serie • 2) Modo Asíncrono • Clear bit SYNC • 3) Habilitar puerto serie • Set bit SPEN • 4) Interrupciones habilitadas • Set bit TXIE • 5) Si se quiere 9º bit de datos • Set bit TX9
PIC 16F873 - Interfaz Serie • 6 ) Habilitar transmision • Set bit TXEN (habilita el bit TXIF) • 7) Si se ha seleccionado 9º bit • Cargar bit en TX9D • 8) Cargar el registro TXREG con los datos: • empieza automáticamente la transmisión
CODIGO PIC - MAIN PROGRAMA PRINCIPAL // Programa principal main(){ // Configurar modulo AD initialice_ad(); // Configurar comunicacion serie serial_port_configure(); while(1){ //Empezar conversion begin_conversion(); //mandar datos send_data(); }
CODIGO PIC - INITIALICE_AD //TRISA asm bsf TRISA,7 // Configuracion de los pines //set_bit( PCFG3,0); //set_bit( PCFG2,0); //set_bit( PCFG1,0); //set_bit( PCFG0,1); //Utilizar 0000 (V+ = Vdd; V- = Vss) asm bcf ADCON1,PCFG3 asm bcf ADCON1,PCFG2 asm bcf ADCON1,PCFG1 asm bcf ADCON1,PCFG0 //set_bit( ADFM,1); // datos en los 10 bits de menos peso asm bsf ADCON1,ADFM // Finalmente Habilitamos modulo AD //Pasamos al banco 0 (00) asm bcf STATUS, RP0 asm bcf STATUS, RP1 //Habilitamos asm bsf ADCON0, ADON } initialice_ad(){ // Configuracion del modulo AD //ADCON0 (bank 0) //set_bit( ADCS0,1); // Frecuencia de adquisicion //set_bit( ADCS1,0); asm bsf ADCON0,ADCS0 asm bcf ADCON0,ADCS1 //set_bit( ADFM,0); // Canal de entrada //set_bit( ADFM,0); //set_bit( ADFM,0); asm bcf ADCON0,CHS2 asm bcf ADCON0,CHS1 asm bcf ADCON0,CHS0 //ADCON1 //Pasamos al banco 1 (01) asm bcf STATUS, RP1 asm bsf STATUS, RP0
CODIGO PIC - SERIAL_PORT //asyncronous mode asm bcf TXSTA,SYNC //Serial port enable //Pasamos al banco 0 (00) asm bcf STATUS, RP1 asm bcf STATUS, RP0 asm bsf RCSTA,SPEN //enable trasnmit //Pasamos al banco 1 (01) asm bcf STATUS, RP1 asm bsf STATUS, RP0 asm bsf TXSTA,TXEN } void serial_port_configure(){ //Pasamos al banco 1 (01) asm bcf STATUS, RP1 asm bsf STATUS, RP0 //configure pins 6,7 asm bsf TRISC,6 asm bsf TRISC,7 // Baud generator (9600) on //I suppose fosc=4Mhz // fosc=4Mhz --> SPBRG=25 // fosc=20Mhz --> SPBRG=129 // y BRGH=1 asm movlw D'25' asm movwf SPBRG asm bsf TXSTA,BRGH
CODIGO PIC - BEGIN_CONVERSION begin_conversion(){ //Pasamos al banco 0 (00) asm bcf STATUS, RP0 asm bcf STATUS, RP1 //empezamos la conversion asm bsf ADCON0, GO_DONE //tenemos que esperar a que se haya acabado la conversion //while (ADCON0 & 0x04) bit GO/DONE //b=0x04; asm movf ADCON0, W asm movwf _b while ((b & 0x04) == 0x04 ){ asm movf ADCON0, W asm movwf _b } }
CODIGO PIC - SEND_DATA //wait until transmitted delay_ms(10); //Pasamos al banco 1 (01) asm bcf STATUS, RP1 asm bsf STATUS, RP0 asm movf ADRESL, W //Pasamos al banco 0 (00) asm bcf STATUS, RP1 asm bcf STATUS, RP0 asm movwf TXREG //wait until transmitted delay_ms(10); } void send_data(){ // load register with data //Pasamos al banco 0 (00) asm bcf STATUS, RP1 asm bcf STATUS, RP0 // Inicio de los datos // transmitimos una "v" ( decimal ->118) asm movlw D'118' asm movwf TXREG delay_ms(10); //transmitimos primero el byte alto y después el bajo //Pasamos al banco 0 (00) asm bcf STATUS, RP1 asm bcf STATUS, RP0 asm movf ADRESH, W asm movwf TXREG
CODIGO PC - PROGRAMA PRINCIPAL while(1){ recibido = Recibe_un_caracter(); if (recibido == 'v'){ //Recibimos parte alta alta = Recibe_un_caracter(); baja = Recibe_un_caracter(); dato = ((alta) << 8 ) + baja; printf("Dato recibido = %d \n",dato); printf("Dato convertido = %f \n", convierte_dato(dato, v_low, v_high)); } }//while }//main void main(){ int i,j; char recibido; unsigned char alta,baja; int dato; int v_low, v_high; Inicializa_Comunicaciones(1,9600); printf("Introduce Referencia V- :"); scanf("%d",&v_low); printf("Introduce Referencia V+ :"); scanf("%d",&v_high); printf("introducida V- = %d\n",v_low); printf("introducida V+ = %d\n",v_high); if (v_low>v_high){ printf("ERROR: Valores incorrectos\n"); return; } printf("Preparado para recibir datos...\n");
CODIGO PC - CONVERTIDOR float convierte_dato(int dato, float low, float high){ float intervalo,margen; float result; intervalo = high - low; //printf("convierte: intervalo=%f\n",intervalo); // 2^10 = 1024 margen = (intervalo / (1024)); //printf("convierte: margen=%f\n",margen); result = low + margen*dato; //printf("convierte: resultado=%f\n",result); return result; }