Advertisement
paulogp

ATmega128: T5 - RS232

Jul 23rd, 2011
177
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.32 KB | None | 0 0
  1. // ATmega128 - RS232
  2. // paulogp
  3.  
  4. /* Pretende-se implementar uma comunicação série RS232 com um PC. O funcionamento deve ser o seguinte:
  5. - O PC envia o caracter "L" obtendo como resposta do µC o nº de amostras actualmente em vigor para a
  6. implementação do filtro seguido do valor da última aquisição obtida.
  7.  
  8. - O PC envia o conjunto de caracteres "Nxy", em que "x" e "y" são caracteres de "0" a "9", indicando
  9. ao µC o número de amostras que deve ser utilizado no filtro digital. P. ex. "N32" para a obtenção de
  10. 32 amostras do sinal. O nº de amostras deve ser uma potência 2. */
  11.  
  12. #include <interrupt.h>
  13. #include <stdio.h>
  14.  
  15. const unsigned char tabela[] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90};
  16.  
  17. unsigned char cnt_500ms = 100;
  18. unsigned char flag_aq = 0;
  19. unsigned char flag_end = 0;
  20. unsigned char n_amostras = 1, n_amostras_bak = 1, n_amostras_new = 1;
  21. unsigned char switches;
  22. unsigned char soma_h, soma_l, media_h, media_l;
  23. unsigned int media;
  24. unsigned int medida=0, d_medida;
  25. unsigned char digito[] = {0, 0, 0, 0};
  26. unsigned char cnt_disp = 0;
  27. unsigned char byte_rx, cnt_rx = 0, buffer_rx[3], flag_rx, cnt_buf, amostras_rx;
  28. char buffer_tx[20];
  29. unsigned char flag_erro;
  30.  
  31. extern void ler_AD(void);
  32.  
  33.  
  34. // Rotina de inicialização do hardware
  35. void inic(void) {
  36.     // inicializacao do PORTO A
  37.     PORTA = 0;
  38.     DDRA = 0b11000000;
  39.  
  40.     // inicializacao do PORTO C
  41.     PORTC = 0xff;
  42.     DDRC = 0xff;
  43.  
  44.     // inicializacao TC0
  45.     OCR0 = 77;
  46.     TCCR0 = 0b00001111;
  47.  
  48.     // inicializacao ADC
  49.     ADMUX = 0;
  50.     ADCSRA = 0b10000111;
  51.  
  52.     // inicializacao USART0
  53.     UBRR0H = 0;
  54.  
  55.     // taxa de 9600bps @16MHz
  56.     UBRR0L = 103;
  57.     UCSR0A = 0;
  58.  
  59.     // enable TX e RX e enable da int de recepcao
  60.     UCSR0B = 0b10011000;
  61.  
  62.     // 8bits de dados, 1 stop bit, sem paridade
  63.     UCSR0C = 0b00000110;
  64.  
  65.     // enable da interrupcao do TC0
  66.     TIMSK |= 2;
  67.  
  68.     // ... do ADC
  69.     ADCSRA |= 0b00001000;
  70.  
  71.     // ... e enable global
  72.     SREG |= 0x80;
  73. }
  74.  
  75. // rotina de interrupcao do ADC
  76. ISR(ADC_vect) {
  77.     // funcao em assembly
  78.     ler_AD();
  79. }
  80.  
  81. // rotina de display
  82. void display(void) {
  83.     // apaga display actual
  84.     PORTC = 0xff;
  85.  
  86.     // incrementa contador de display
  87.     cnt_disp++;
  88.  
  89.     if (cnt_disp == 4) {
  90.         cnt_disp = 0;
  91.     }
  92.  
  93.     // selecciona display
  94.     PORTA = cnt_disp << 6;
  95.  
  96.     // escreve valor
  97.     PORTC = tabela[digito[cnt_disp]];
  98. }
  99.  
  100. // rotina de interrupcao do TC0 (5 em 5ms)
  101. ISR(TIMER0_COMP_vect) {
  102.     // verifica se passaram 500ms
  103.     cnt_500ms--;
  104.  
  105.     if (cnt_500ms == 0) {
  106.         cnt_500ms = 100;
  107.         flag_aq = 1;
  108.     }
  109.  
  110.     // faz o display da medida actual
  111.     display();
  112. }
  113.  
  114. // rotina de interrupcao da USART0 - RX
  115. ISR(USART0_RX_vect) {
  116.     // le o byte recebido
  117.     byte_rx = UDR0;
  118.  
  119.     // verifica se e o 1 byte
  120.     if (cnt_rx == 0) {
  121.         // guarda no buffer de recepcao
  122.         buffer_rx[cnt_rx] = byte_rx;
  123.  
  124.         switch(byte_rx) {
  125.             // se for um "L"...
  126.             case 'L':
  127.                 // activa flag da RX completa
  128.                 flag_rx = 1;
  129.                 break;
  130.  
  131.             // se for um "N"...
  132.             case 'N':
  133.                 // prepara cnt para novo byte
  134.                 cnt_rx++;
  135.                 break;
  136.  
  137.             default:
  138.                 flag_rx = 1;
  139.         }
  140.     }
  141.     // se nao for o 1o byte
  142.     else {
  143.         // verifica se e um digito
  144.         if ((byte_rx >= '0') && (byte_rx <= '9')) {
  145.             // guarda no buffer
  146.             buffer_rx[cnt_rx] = byte_rx;
  147.  
  148.             // incrementa ponteiro
  149.             cnt_rx++;
  150.  
  151.             // verifica se terminou mensagem
  152.             if (cnt_rx == 3) {
  153.                 // se terminou: activa flag
  154.                 flag_rx = 1;
  155.             }
  156.         }
  157.     }
  158. }
  159.  
  160. // transmite buffer
  161. void transmite_buffer(void) {
  162.     // inicializa ponteiro do buffer
  163.     cnt_buf = 0;
  164.  
  165.     while (buffer_tx[cnt_buf] != 0) {
  166.         // espera registo de dados esteja vazio
  167.         while ((UCSR0A & 0x20) == 0);
  168.  
  169.         // transmite caracter
  170.         UDR0 = buffer_tx[cnt_buf];
  171.  
  172.         cnt_buf++;
  173.     }
  174. }
  175.  
  176. // processa RX
  177. void processa_rx(void) {
  178.     // prepara contador para nova recepcao
  179.     cnt_rx = 0;
  180.  
  181.     // verifica qual o 1o byte
  182.     switch (buffer_rx[0]) {
  183.         // se for 'L'...
  184.         case 'L':
  185.             // transmite medida
  186.             sprintf(buffer_tx "&d\n\r", (int)medida);
  187.             transmite_buffer();
  188.             break;
  189.  
  190.         // se for 'N' calcula nº de amostras
  191.         case 'N':
  192.             amostras_rx = (buffer_rx[1] & 0xCF) * 10 + (buffer_rx[2] & 0xCF);
  193.  
  194.             // verifica se e potencia de 2
  195.             switch (amostras_rx) {
  196.                 case 1:
  197.                     n_amostras_new = 1;
  198.                     flag_erro = 0;
  199.                     break;
  200.  
  201.                 case 2:
  202.                     n_amostras_new = 2;
  203.                     flag_erro = 0;
  204.                     break;
  205.  
  206.                 case 4:
  207.                     n_amostras_new = 4;
  208.                     flag_erro = 0;
  209.                     break:
  210.  
  211.                 case 8:
  212.                     n_amostras_new = 8;
  213.                     flag_erro = 0;
  214.                     break;
  215.  
  216.                 case 16:
  217.                     n_amostras_new = 16;
  218.                     flag_erro = 0;
  219.                     break;
  220.  
  221.                 case 32:
  222.                     n_amostras_new = 32;
  223.                     flag_erro = 0;
  224.                     break;
  225.  
  226.                 case 64:
  227.                     n_amostras_new = 64;
  228.                     flag_erro = 0;
  229.                     break;
  230.  
  231.                 default:
  232.                     flag_erro = 1;
  233.             }
  234.     }
  235.  
  236.     // se nº de amostras correcto...
  237.     if ((buffer_rx[0] == 'N') && (flag_erro == 0)) {
  238.         // transmite nº de amostras
  239.         sprintf(buffer_tx, "N amostras = %d\n\r", n_amostras_new);
  240.         transmite_buffer();
  241.     }
  242. }
  243.  
  244. int main(void) {
  245.     inic();
  246.  
  247.     while (1) {
  248.         // verifica switches
  249.         switches = PINA & 0b00111111;
  250.  
  251.         switch (switches) {
  252.             case 0b00111110:
  253.                 n_amostras_new = 1;
  254.                 break;
  255.  
  256.             case 0b00111101:
  257.                 n_amostras_new = 8;
  258.                 break;
  259.  
  260.             case 0b00111011:
  261.                 n_amostras_new = 16;
  262.                 break;
  263.  
  264.             case 0b00110111:
  265.                 n_amostras_new = 32;
  266.         }
  267.  
  268.         // se e necessario nova aquisicao
  269.         if (flag_aq) {
  270.             soma_h = soma_l = 0;
  271.  
  272.             // inicializa numero de amostras
  273.             n_amostras = n_amostras_new;
  274.             n_amostras_bak = n_amostras_new;
  275.  
  276.             // inicio da primeira conversao
  277.             ADCSRA |= 0x40;
  278.  
  279.             // reset da flag de aquisicao
  280.             flag_aq = 0;
  281.         }
  282.  
  283.         if (flag_end) {
  284.             // calcula media em 16 bits
  285.             media = (media_h << 8) + media_l;
  286.  
  287.             // calcula media em mV
  288.             medida = (long int)media * 5000 / 1024;
  289.             d_medida = medida;
  290.  
  291.             // extrai digitos
  292.             digito[0] = d_medida / 10000;
  293.             d_medida = d_medida % 1000;
  294.  
  295.             digito[1] = d_medida / 100;
  296.             d_medida = d_medida % 100;
  297.  
  298.             digito[2] = d_medida / 10;
  299.  
  300.             digito[3] = d_medida % 10;
  301.  
  302.             // desactiva flag
  303.             flag_end = 0;
  304.         }
  305.  
  306.         // se recebeu comunicacao do exterior
  307.         if (flag_rx == 1) {
  308.             processa_rx();
  309.  
  310.             // desactiva flag
  311.             flag_rx = 0;
  312.         }
  313.     }
  314. }
  315.  
  316.  
  317.  
  318. // ficheiro assembly
  319. ; LEITURA DO ADC
  320.  
  321. #define __SFT_OFFSET 0
  322.  
  323. #include <interrupt.h>
  324.  
  325. .global ler_AD
  326. .extern soma_l
  327. .extern soma_h
  328. .extern n_amostras
  329. .extern n_amostras_bak
  330. .extern media_h
  331. .extern media_l
  332. .extern flag_end;
  333.  
  334.  
  335. ler_AD:
  336.     ; guarda registos
  337.     push r0
  338.     push r1
  339.     push r2
  340.     push r3
  341.     push r16
  342.  
  343.     ; leitura do AD
  344.     in r0, ADCL
  345.     in r1, ADCH
  346.  
  347.     ; leitura da variavel soma (inteiro)
  348.     lds r2, soma_l
  349.     lds r3, soma_h
  350.  
  351.     ; soma valores
  352.     add r2, r0
  353.     adc r3, r1
  354.  
  355.     ; guarda resultado
  356.     sts soma_l, r2
  357.     sts soma_h, r3
  358.  
  359.     ; decrementa contador de amostras
  360.     lds r0, n_amostras
  361.     dec r0
  362.     sts n_amostras, r0
  363.  
  364.     ; verifica se terminou as amostragens
  365.     breq calc_media
  366.  
  367.     ; se nao terminou desencadeia nova aquisicao
  368.     sbi ADCSRA, 6
  369.  
  370.     jmp f_ler_AD
  371.  
  372. calc_media:
  373.     ; se terminou, vai calcular media
  374.     lds r0, n_amostras_bak
  375.  
  376. shift:
  377.     lsr r0
  378.     breq f_shift
  379.     clc
  380.     ror r3
  381.     ror r2
  382.     jmp shift
  383.  
  384. f_shift:
  385.     ; guarda media
  386.     sts media_h, r3
  387.     sts media_l, r2
  388.     ldi r16, 1
  389.  
  390.     ; activa flag aquisicao completa
  391.     sts flag_end, r16
  392.  
  393. f_ler_AD:
  394.     ; recupera registos
  395.     pop r16
  396.     pop r3
  397.     pop r2
  398.     pop r1
  399.     pop r0
  400.     ret
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement