Exemplos ccs
Upcoming SlideShare
Loading in...5
×

Like this? Share it with your network

Share
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
    Be the first to like this
No Downloads

Views

Total Views
825
On Slideshare
825
From Embeds
0
Number of Embeds
0

Actions

Shares
Downloads
45
Comments
0
Likes
0

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. PROGRAMAS DE EXEMPLOS DO COMPILADOR CCS 1. Exemplos de xestión de portos 1.1. Xestión de portos en C 1.1.a) Xestión a través da memoria RAMA configuración dos portos correspondentes dos PIC faise a través dos rexistros especiais TRISX, quedeterminan os pins dos portos correspondentes que serán utilizados como entradas (1 no bit deconfiguración) ou como saídas (0 no bit de configuración). Os valores lense ou sácanse a través dos portoscorrespondentes PORTX. Unha forma de controlar a configuración e os valores recibidos/transmitidos polos portos é definindoa súa posición de memoria como unha variable da función a través da directiva #BYTE.Logo podemos escribir no porto ou ler do porto un valor. Tamén podemos manexar independentemente osbits.PORTX = valor // Saca polo porto X os bits correspondentes a valorvalor = PORTX // Asigna o dato do porto á variable valorbit_clear (var, bit) // Pon 0 no bit especificado da variablebit_set (var, bit) // Pon 1 no bit especificado da variablebit_test (var, bit) // Recolle o valor do bit especificado da variableswap (var) // Intercambia os 4 bits de maior peso (nibble superior) cos de menor peso (nibble // inferior)Exemplo 1: Terminal RB0 como entrada, RB1 como saída. O valor da entrada é reflectido na saída. Para poder manexar a entrada con un interruptor conectado ou non a terra debemos activar as resistencias internas de pull-up para obter un nivel alto cando o interruptor estea desconectado.Solución 1: Mediante o manexo das direccións de memoria RAM.#include <16F84A.h> // O PIC empregado#fuses XT, NOWDT // Fusibles: oscilador cristal (<=4 MHz) // sen activar can gardián#use delay(clock=4000000) // Velocidade do reloxo 4 MHz#BYTE TRISB = 0x86 // Posición na RAM do rexistro de configuración do porto B#BYTE PORTB = 0x06 // Posición do porto B na RAM#BYTE OPTION_REG = 0x81 // Posición deste rexistro, para activar pull-up en Bvoid main () { bit_clear (OPTION_REG,7); // Habilitación do pull-up en B bit_set (TRISB,0); // Pin 0 de configuración a 1: entrada bit_clear (TRISB,1); // Pin 1 de configuración a 0: saída bit_clear (PORTB,1); // Sacamos un 0 polo pin 1 do porto B while (1) { // Bucle infinito if (bit_test(PORTB,0) == 1) // Comprobamos se o bit 0 vale 1 (RB0==1??)
  • 2. bit_clear(portb,1); // Se vale 1, sacamos un 0 pola saída (bit 1) else bit_set(portb,1); // Se vale 0 sacamos un 1 polo bit 1 do porto B }} 1.1.b) Xestión mediante as directivas do compiladorSolución 2: Mediante as directivas do compilador de C. O compilador ten funcións especificas para traballar cos portos:output_X (valor) // Saca un valor binario de 8 bits polo porto X (0-255)input_X (valor) // Obtén o valor do porto Xset_tris_X (valor) // Configura o rexistro TRISX poñéndolle o valor (0-255)port_b_pullups (valor) // valor=TRUE habilita pull-ups; valor=FALSE(=0) desabilítaoget_trisX() // Devolve o valor do rexistro TRISX Ademais podemos manexar independentemente os pins dos portos (definidos mediante parámetrosno ficheiro de encabezamento do chip correspondente) con certas funcións:output_low(pin) // Pon o pin a 0output_high(pin) // Pon o pin a 1output(pin,valor) // Pon o pin ao valor especificadooutput_toggle(pin) // Complementa o valor do pinoutput_float(pin) // Pin en drenador aberto, saída flotanteinput_state(pin) // Le o valor do pin, sen modificar o sentido do terminalinput(pin) // Le o valor do pin e pono como entrada dependendo do tipo #USE *_IO usado#USE FAST_IO (PORTO) Utilízase o porto correspondente para sacar valores con ouput_x() ou lelos con input_x() pero senmodificar a configuración do porto. Os rexistros TRIS de configuración deben estar correctamente definidos.#include <16F84A.h> // O PIC empregado#fuses XT, NOWDT // Fusibles: oscilador cristal (<=4 MHz) // sen activar can gardián#use delay(clock=4000000) // Velocidade do reloxo 4 MHz#use fast_io (B) // Forma de configurar porto Bvoid main () { port_b_pullups (TRUE); // Habilitación do pull-up en B set_tris_B(0x01); // Pin 0=1 (entrada); pin 1=0 (saída) output_low(PIN_B1); // Sacamos un 0 polo pin 1 do porto B while (1) { // Bucle infinito if (input(PIN_B0) == 1) // Comprobamos se o bit 0 vale 1 (RB0==1??) output_low(PIN_B1); // Se vale 1, sacamos un 0 pola saída (bit 1) else output_high(PIN_B1); // Se vale 0 sacamos un 1 polo bit 1 do porto B }}#USE STANDARD_IO(PORTO)
  • 3. O compilador modifica o TRIS correspondente para asegurarse de que os terminais usados esteancorrectamente configurados: saída coa función output_x() e entrada coa función input_x(). É a directiva quese utiliza por defecto.#include <16F84A.h> // O PIC empregado#fuses XT, NOWDT // Fusibles: oscilador cristal (<=4 MHz) // sen activar can gardián#use delay(clock=4000000) // Velocidade do reloxo 4 MHz#use standard_io (B) // Forma de configurar porto Bvoid main () { port_b_pullups (TRUE); // Habilitación do pull-up en B // Agora non fai falla configurar o TRISB output_low(PIN_B1); // Sacamos un 0 polo pin 1 do porto B while (1) { // Bucle infinito if (input(PIN_B0) == 1) // Comprobamos se o bit 0 vale 1 (RB0==1??) output_low(PIN_B1); // Se vale 1, sacamos un 0 pola saída (bit 1) else output_high(PIN_B1); // Se vale 0 sacamos un 1 polo bit 1 do porto B }}#USE FIXED_IO(PORTO_OUTPUTS=pin*, ...) Na directiva só se indican os terminais de saída e o compilador xera o código de configuracióncorrespondente, independentemente de que as operacións realizadas sexan de entrada ou de saída.#include <16F84A.h> // O PIC empregado#fuses XT, NOWDT // Fusibles: oscilador cristal (<=4 MHz) // sen activar can gardián#use delay(clock=4000000) // Velocidade do reloxo 4 MHz#use fixed_io (b_outputs=pin_b1) // Só pin 1 do porto B como saídavoid main () { port_b_pullups (TRUE); // Habilitación do pull-up en B // Agora non fai falla configurar o TRISB output_low(PIN_B1); // Sacamos un 0 polo pin 1 do porto B while (1) { // Bucle infinito if (input(PIN_B0) == 1) // Comprobamos se o bit 0 vale 1 (RB0==1??) output_low(PIN_B1); // Se vale 1, sacamos un 0 pola saída (bit 1) else output_high(PIN_B1); // Se vale 0 sacamos un 1 polo bit 1 do porto B }} 1.1.c) Xestión mediante punteirosSolución 3: Mediante a utilización de punteiros dirixidos ás posicións de memoria correspondentes. Os punteiros débense definir como enteiros (int*).#define TRISA (int*) 0x85#define PORTA (int*) 0x05 Os rexistros manéxanse co operador de indirección *.int valor;
  • 4. valor = *portoa; Os terminais lense e escríbense utilizando operacións lóxicas con bits.*portoa != 0b0000001; // RA0 = 1 mediante OR (resto dos bits do porto non cambian*portoa &= 0b11111101; // RA1 = 0 mediante AND (resto dos bits do porto non cambianbit0 = (*portoa & 0b00000001); // Lemos o bit 0 do portoaO exemplo quedaría:#include <16F84A.h> // O PIC empregado#fuses XT, NOWDT // Fusibles: oscilador cristal (<=4 MHz) // sen activar can gardián#use delay(clock=4000000) // Velocidade do reloxo 4 MHz#define TRISB (int*) 0x86 // Contido de TRISB na dirección 0x86#define PORTB (int*) 0x06 // Contido de PORTB na dirección 0x06#define OPTION (int*) 0x81 // Contido de OPTION na dirección 0x81void main () { *option &= 0b0111111; // Habilitación do pull-up en B poñendo 0 no bit 7 do // OPTION_REG (variable option) *trisb = 0x01; // RB0 entrada, RB1 (e o resto) saída *portb = 0x00; // Sacamos un 0 polo pin 1 do porto B while (1) { // Bucle infinito if (*portb & 0x01) // Comprobamos se o bit 0 vale 1 (RB0==1??) *portb = 0x00; // Se vale 1, sacamos un 0 pola saída (bit 1) else *portb = 0x02; // Se vale 0 sacamos un 1 polo bit 1 do porto B }} 1.1.d) Exemplo utilizaciónExemplo 2: Realizar un contador de 0 a 99 con dous displays de 7 segmentos de cátodo común. O díxito das decenas debe estar apagado de 0 a 9.#include <16f84A.h>#use delay (clock = 4000000)#fuses XT, NOWDT, NOPROTECT, NOPUT#use standard_io (A)#use standard_io (B)byte CONST display[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};// O valor hexadecimal proporciona os 7 bits para activar os leds e ver os números de 0 a 9main() { byte ud=0, dec=0; output_b(0); for (;;) { for (dec=0;dec<10;dec++) { // Bucle externo para decenas for (ud=0;ud<10;ud++) { // Bucle interno para unidades output_a (0x02); // Alimentamos cun 0 visualizador de unidades output_b(display[ud]); // Percorremos as unidades delay_ms(50); // Parando un pouco en cada unha if (dec==0) output_a(0x03); // Se non hai decenas non se ve 0 else output_a (0x01); // Se as hai alimentamos o visulizador decenas
  • 5. output_b(display[dec]); // Percorremos as decenas delay_ms(50); // Parando un pouco en cada una } } }} 1.2. Xestión de dispositivos de entrada e saída 1.2.a) LCD O compilador inclúe ficheiros en C para traballar con visualizadores LCD. Este ficheiro pódesemodificar para adaptalo ás nosas necesidades.NOTA: A MODIFICACIÓN DOS FICHEIROS DO COMPILADOR DEBE REALIZARSE CON CAUTELA, COIDANDO DE FACER COPIA DO FICHEIRO ORIXINAL E GARDAR CON OUTRO NOME O ARQUIVO MODIFICADO.Un dos arquivos é lcd.c, no cartafol drivers, e debe incluírse para a compilación no noso ficheiro fonte.Dentro deste arquivo existen varias funcións definidas que facilitan o manexo do visualizador.lcd_init ();Configúrao para traballar con 4 bits, dúas liñas e tamaño de 5x8 puntos por caracter, sen visualización docursor e con xestión automática do punteiro de direccións. As catro liñas de funcionamento serven para axestión e para a escritura e lectura de datos. Débese chamar en primeiro lugar.lcd_gotoxy (byte x, byte y);Indica a posición de traballo no LCD: (1,1) é a primeira columna da primeira liña e (2,1) é a primeira columnada segunda liña. O LCD ten 2 liñas e 16 caracteres.lcd_getc (byte x, byte y);Le o contido da posición (x,y).lcd_putc (char s);Escribe a variable tipo char na posición correspondente. Permite os seguintes caracteres especiais: f limpa o LCD n cursor á posición (1,2) b o cursor retrocede unha posiciónTamén podemos utilizar unha función semellante a printf () do C para utilizar o LCD.printf (string) // string é unha cadea ou array de caracteresprintf (cstring, valores ...) // valores é unha lista de variables separadas por comasprintf (fname, cstring, valores ...) // fname é unha funciónA función permite a utilización de formato de presentación de variables tipo %nt, onde n é opcional e indicaa cantidade de caracteres e/ou decimais que se representan e t indica o tipo de formato para a variable.NOTA: PARA MAIOR INFORMACIÓN SOBRE AS FUNCIÓNS ESPECÍFICAS DO COMPILADOR PÓDESE CONSULTAR A AXUDA DO MESMO, NO APARTADO BUILT- IN FUNCTIONS.Exemplos de utilización:byte x, y, z;printf (“Ola”);printf (“Valor => %2xnr”, get_rtcc () );printf (“%2u %X %4xnr”, x, y, z);printf (LCD_PUTC, “n=%u”, n);
  • 6. O ficheiro está configurado para traballar co porto D, pero non comentar unha das liñas permite utilizar oporto B. A utilización doutros portos require modificacións máis amplas. A conexión do porto utilizado cospins do LCD está tamén indicada no arquivo.Exemplo 3: Realizar un menú de control mediante dous pulsadores: un permite seleccionar entre os tres elementos do menú que aparecen no LCD e o outro executa a función asociada a ese elemento (modificar unha das saídas para acender o LED asociado).#include <16f84A.h>#fuses XT, NOWDT#use delay (clock=4000000)#include <lcd_b.c> // O ficheiro modificado para traballar co porto B#use fast_io (A)#use standard_io (B)enum funciones {med, cal, ini}; // Asigna un valor a cada elemento // med = 0, cal = 1, ini = 2void medir (void){ set_tris_a (0x03); // Pins 0 e 1 entradas, resto do porto A saídas output_toggle(pin_A2); // A función asociada a medir é cambiar o estado do pin 2}void calibrar (void){ set_tris_a (0x03); // Pins 0 e 1 entradas, resto do porto A saídas output_toggle(pin_A3); // A función asociada a calibrar é cambiar o estado do pin 3}void inicializar (void){ set_tris_a (0x03); output_toggle(pin_A4); // A función asociada a calibrar é cambiar o estado do pin 4} /* Coidado, este pin é de saída en drenador aberto e necesita resistencia de pull-up externa para mostrar un nivel alto */void run_func (int numfunc){ switch (numfunc){ // Segundo o valor de numfunc realizamos a función asociada case med: // med vale 0, coa orde enum medir(); break; case cal: // cal vale 1, pola orde enum calibrar (); break; case ini: inicializar (); // ini vale 2, pola orde enum break; }}void main () { char item; // Percorremos o menú secuencialmente char n_menus = 3; // Para volver ao primeiro elemento ao rematalos
  • 7. lcd_init(); // Primeira función para traballar co LCD while(1) { if (input(pin_A0 == 1)) { // A cada pulsación no pin A0 item++; // avanzamos un elemento de menú delay_ms (300); // Retardo para evitar rebotes lcd_putc (f); // Borramos LCD } if (item > (n_menus-1)) // Rematamos os elementos do menú? item = 0; // Se os rematamos volvemos ao principio switch (item) { // Poñemos no LCD o elemento de menu case 0: lcd_gotoxy (1,1); printf (lcd_putc, “MEDIR”); lcd_gotoxy (1,1); break; case 1: printf (lcd_putc, “CALIBRAR”); lcd_gotoxy (1,1); break; case 2: printf (lcd_putc, “INICIALIZAR”); lcd_gotoxy (1,1); break; } if (input (pin_A1) == 1) { // Poñendo A1 en alta ... delay_ms (200); // retardo para evitar rebotes ... run_func (item); // Executamos a función asociada a ese elemento do menú } }} 1.2.b) LCD GRÁFICOPara o manexo de LCD gráficos o compilador proporciona varios arquivos para utilizalos comocontroladores: glcd.c, graphics.c, hdm64gs12.c. Tamén podemos buscar controladores para osvisualizadores en internet. A maioría dos controladores indican os terminais que se utilizan para o manexo, as conexiónsnecesarias cos portos do PIC e as funcións que pode manexar: liñas, círculos, rectángulos, ... e osparámetros necesarios para utilizalas. É conveniente botar unha ollada a estes arquivos, e tamén editalospara adaptalos ás nosas necesidades. Para escribir as letras no modo gráfico utilízase unha matriz na que se definen mediante valoreshexadecimais os pixels que se deben acender en cada unha das columnas coas que se definen oscaracteres (no noso caso caracteres de 5x7, cinco columnas de 7 puntos). Podemos modificar estes valorespara cambiar o aspecto dos caracteres ou definir outros novos (por exemplo para poder manexar Ñ, ñ, Á, áou outros non incluídos no controlador).
  • 8. O visualizador ten dous terminais de selección CS 1 e CS 2 , que manexan as dúas metadesverticais en que está dividido. No controlador utilizado debemos cambiar a asignación dos pins que osmanexan para lograr unha correcta visualización. As funcións definidas nestes controladores son as siguintes:glcd_init (mode)Acende se mode é ON ou apaga se mode é OFF o LCD. Debe ser a primeira que se chama.glcd_pixel(x,y,cor)Pode activarse ou desactivarse para que o pixel apareza iluminado ou non (só admite dúas cores).glcd_fillScreen(cor)Enche o visualizador coa cor seleccionada.glcd_update()Escribe o contido da RAM no LCD.glcd_line(x1,y1,x2,y2,cor)Debuxa unha liña entre o primeiro punto e o segundo da cor indicada (ON ou OFF)glcd_rect(x1,y1,x2,y2,fill,cor)Debuxa un rectángulo dando o vértice superior dereito e o inferior esquerdo, o recheo e a cor.glcd_bar(x1,y1,x2,y2,ancho,cor)Debuxa unha barra, co ancho especificado en pixels.glcd_circle(x,y,radio,fill,cor)Debuxa un círculo dando o centro e o radio, recheo ou non e coa cor activada ou non.glcd_text57(x,y,textptr,tamaño,cor)Comezando no punto indicado, escribe o texto ao que apunta textptr (punteiro). O texto debe rematar cocaracter nulo e pódese escoller o tamaño (número enteiro) e activar ou non a cor.Exemplo 4: Visualizar nun LCD gráfico o estado das entradas do porto A, mediante un rectángulo recheo ou non segundo a entrada correspondente sexa 1 ou 0.#include <18F452.h>#fuses HS,NOWDT,NOPROTECT,NOLVP#use delay(clock=8000000)#include <HDM64GS12.c>#include <graphics.c>#use standard_io(a)void main() { CHAR A5[ ]="A5"; CHAR A4[ ]="A4"; CHAR A3[ ]="A3"; CHAR A2[ ]="A2"; CHAR A1[ ]="A1"; CHAR A0[ ]="A0"; CHAR IN[ ]="PUERTO A"; glcd_init(ON); glcd_text57(33, 30,A5, 1, 1); glcd_text57(49, 30,A4, 1, 1); glcd_text57(65, 30,A3, 1, 1); glcd_text57(81, 30,A2, 1, 1);
  • 9. glcd_text57(97, 30,A1, 1, 1); glcd_text57(113, 30,A0, 1, 1); glcd_text57(30,5,IN, 2, 1);while(1){ if (input_state(PIN_A5)==0) glcd_rect(32,40,46,60,1,1); else glcd_rect(32,40,46,60,1,0);glcd_rect(32,40,46,60,0,1); if (input_state(PIN_A4)==0)glcd_rect(48,40,62,60,1,1); else glcd_rect(48,40,62,60,1,0);glcd_rect(48,40,62,60,0,1); if (input_state(PIN_A3)==0) glcd_rect(64,40,78,60,1,1); else glcd_rect(64,40,78,60,1,0);glcd_rect(64,40,78,60,0,1); if (input_state(PIN_A2)==0) glcd_rect(80,40,94,60,1,1); else glcd_rect(80,40,94,60,1,0); glcd_rect(80,40,94,60,0,1); if (input_state(PIN_A1)==0) glcd_rect(96,40,110,60,1,1); else glcd_rect(96,40,110,60,1,0);glcd_rect(96,40,110,60,0,1); if (input_state(PIN_A0)==0) glcd_rect(112,40,126,60,1,1); else glcd_rect(112,40,126,60,1,0);glcd_rect(112,40,126,60,0,1); delay_ms(400); }} Os controladores de LCD utilizados neste exemplo usan os portos B e C para o control e o porto Dpara os datos. A simulación é correcta, pero no LCD real debemos cambiar os pins de selección das cúasmetades CS 1 e CS 2 . Tamén adaptamos o controlador para manexar o visualizador mediante osportos B e D. Coma sempre, facemos copia dos controladores orixinais antes de modificalos. 1.2.c) TECLADOO compilador inclúe tamén controladores para manexar teclados, en concreto un teclado matricial de 3x4. Oarquivo kbd.c incorpora as seguintes funcións:kbd_init()Inicializa o sistema. Debe chamarse antes do uso do teclado.kbd_getc()Devolve o valor da tecla pulsada. O valor atópao na táboa que ten programada en forma de matriz de 4x3(catro filas e tres columnas). O controlador utiliza o porto D para manexar o teclado, pero pódese modificar facilmente paratraballar co porto B. Tamén se poden configurar as conexións de filas e columnas e o patrón de teclasasignadas. Para o funcionamento correcto o porto utilizado debe ter activado o pull-up para ler un nivel altocando non se pulsa ningunha tecla. As pulsacións das teclas recóllense como caracteres ASCII. Para poder operar con elas comonúmeros debemos restarlle o valor decimal 48 (código ASCII do número 0).Exemplo 5: Deseñar un sistema que permita abrir unha porta ao introducir o código correcto a través dun teclado. Indicar mediante unha pantalla LCD a apertura ou non da porta.No exemplo gardaremos a clave da porta na memoria EEPROM, para poder modificala de forma doada.#include <16f84A.h>#fuses xt, nowdt, noput, noprotect#use delay (clock = 4000000)
  • 10. #use standard_io(A)#include <lcd_b.c>#include <kbd_b.c>#include <stdlib.h>#rom 0x2100={1, 2, 3} // Posición de inicio da EEPROM e datos gardadosvoid main() { char k; // Garda a pulsación int i; // Percorre os elementos da matriz char data[3], clave[3]; // Matrices para gardar as pulsacións e a clave lcd_init(); kbd_init(); port_b_pullups(TRUE); // Pull-up activo no porto que recibe pulsacións do teclado while (TRUE){ i=0; printf(lcd_putc, "fPulsar tecla 1n"); // Indicamos recepción primeiro número while (i<=2){ // O índice de matriz para o primeiro número é 0 k=kbd_getc(); if (k!=0){ // Recollemos pulsación? data[i]=k; // Asignamos valor na matriz i++; // Seguinte índice printf(lcd_putc, "fPulsar tecla %un", i+1); } } for (i=0;i<=2;i++) clave[i]=read_eeprom(i); // Lemos ROM e asignámoslle un elemento da matriz if ((data[0]==clave[0])&&(data[1]==clave[1])&&(data[2]==clave[2])) { // Comprobamos se o introducido coincide co gardado printf(lcd_putc, "fAbrindo portan"); output_high(pin_A0); // Se coincide abrimos porta delay_ms(500); output_low(pin_A0); // Pulso en alta de 0,5 s para excitar o relé } else printf (lcd_putc, "fPorta pechadan"); delay_ms(1000); }}Neste exemplo tanto o teclado como o visualizador LCD están manexados co porto B, mentres a saída setoma do pin 0 do porto A.Exemplo 6: Elaborar un programa que permita sacar por un pin un sinal PWM proporcional ao valor introducido a través dun teclado. O sinal PWM será utilizado para controlar a velocidade dun motor, de maneira proporcional ao valor introducido.Utilizamos unha variable tipo int ou char para definir os tempos en alta e en baixa do sinal, de maneira queo valor máximo sexa 255. Así, se o ciclo de traballo é 100 %, o valor do tempo en alta será 255 e o dotempo en baixa será 0. Para indicar cun valor numérico entre 0 e 9 o ciclo de traballo deberiamos facerlle
  • 11. 255corresponder o 100 % ao valor 9, e por tanto ×N a cada valor N posible. Para non manexar valores 9 255decimais (variables float), que ocupan moito espazo en memoria, utilizaremos en lugar de o valor 9enteiro máis próximo: 28. Ao tempo en baixa corresponderalle o valor 255 - (tempo en alta).