Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // ATmega128 - RS232
- // paulogp
- /* Pretende-se implementar uma comunicação série RS232 com um PC. O funcionamento deve ser o seguinte:
- - O PC envia o caracter "L" obtendo como resposta do µC o nº de amostras actualmente em vigor para a
- implementação do filtro seguido do valor da última aquisição obtida.
- - O PC envia o conjunto de caracteres "Nxy", em que "x" e "y" são caracteres de "0" a "9", indicando
- ao µC o número de amostras que deve ser utilizado no filtro digital. P. ex. "N32" para a obtenção de
- 32 amostras do sinal. O nº de amostras deve ser uma potência 2. */
- #include <interrupt.h>
- #include <stdio.h>
- const unsigned char tabela[] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90};
- unsigned char cnt_500ms = 100;
- unsigned char flag_aq = 0;
- unsigned char flag_end = 0;
- unsigned char n_amostras = 1, n_amostras_bak = 1, n_amostras_new = 1;
- unsigned char switches;
- unsigned char soma_h, soma_l, media_h, media_l;
- unsigned int media;
- unsigned int medida=0, d_medida;
- unsigned char digito[] = {0, 0, 0, 0};
- unsigned char cnt_disp = 0;
- unsigned char byte_rx, cnt_rx = 0, buffer_rx[3], flag_rx, cnt_buf, amostras_rx;
- char buffer_tx[20];
- unsigned char flag_erro;
- extern void ler_AD(void);
- // Rotina de inicialização do hardware
- void inic(void) {
- // inicializacao do PORTO A
- PORTA = 0;
- DDRA = 0b11000000;
- // inicializacao do PORTO C
- PORTC = 0xff;
- DDRC = 0xff;
- // inicializacao TC0
- OCR0 = 77;
- TCCR0 = 0b00001111;
- // inicializacao ADC
- ADMUX = 0;
- ADCSRA = 0b10000111;
- // inicializacao USART0
- UBRR0H = 0;
- // taxa de 9600bps @16MHz
- UBRR0L = 103;
- UCSR0A = 0;
- // enable TX e RX e enable da int de recepcao
- UCSR0B = 0b10011000;
- // 8bits de dados, 1 stop bit, sem paridade
- UCSR0C = 0b00000110;
- // enable da interrupcao do TC0
- TIMSK |= 2;
- // ... do ADC
- ADCSRA |= 0b00001000;
- // ... e enable global
- SREG |= 0x80;
- }
- // rotina de interrupcao do ADC
- ISR(ADC_vect) {
- // funcao em assembly
- ler_AD();
- }
- // rotina de display
- void display(void) {
- // apaga display actual
- PORTC = 0xff;
- // incrementa contador de display
- cnt_disp++;
- if (cnt_disp == 4) {
- cnt_disp = 0;
- }
- // selecciona display
- PORTA = cnt_disp << 6;
- // escreve valor
- PORTC = tabela[digito[cnt_disp]];
- }
- // rotina de interrupcao do TC0 (5 em 5ms)
- ISR(TIMER0_COMP_vect) {
- // verifica se passaram 500ms
- cnt_500ms--;
- if (cnt_500ms == 0) {
- cnt_500ms = 100;
- flag_aq = 1;
- }
- // faz o display da medida actual
- display();
- }
- // rotina de interrupcao da USART0 - RX
- ISR(USART0_RX_vect) {
- // le o byte recebido
- byte_rx = UDR0;
- // verifica se e o 1 byte
- if (cnt_rx == 0) {
- // guarda no buffer de recepcao
- buffer_rx[cnt_rx] = byte_rx;
- switch(byte_rx) {
- // se for um "L"...
- case 'L':
- // activa flag da RX completa
- flag_rx = 1;
- break;
- // se for um "N"...
- case 'N':
- // prepara cnt para novo byte
- cnt_rx++;
- break;
- default:
- flag_rx = 1;
- }
- }
- // se nao for o 1o byte
- else {
- // verifica se e um digito
- if ((byte_rx >= '0') && (byte_rx <= '9')) {
- // guarda no buffer
- buffer_rx[cnt_rx] = byte_rx;
- // incrementa ponteiro
- cnt_rx++;
- // verifica se terminou mensagem
- if (cnt_rx == 3) {
- // se terminou: activa flag
- flag_rx = 1;
- }
- }
- }
- }
- // transmite buffer
- void transmite_buffer(void) {
- // inicializa ponteiro do buffer
- cnt_buf = 0;
- while (buffer_tx[cnt_buf] != 0) {
- // espera registo de dados esteja vazio
- while ((UCSR0A & 0x20) == 0);
- // transmite caracter
- UDR0 = buffer_tx[cnt_buf];
- cnt_buf++;
- }
- }
- // processa RX
- void processa_rx(void) {
- // prepara contador para nova recepcao
- cnt_rx = 0;
- // verifica qual o 1o byte
- switch (buffer_rx[0]) {
- // se for 'L'...
- case 'L':
- // transmite medida
- sprintf(buffer_tx "&d\n\r", (int)medida);
- transmite_buffer();
- break;
- // se for 'N' calcula nº de amostras
- case 'N':
- amostras_rx = (buffer_rx[1] & 0xCF) * 10 + (buffer_rx[2] & 0xCF);
- // verifica se e potencia de 2
- switch (amostras_rx) {
- case 1:
- n_amostras_new = 1;
- flag_erro = 0;
- break;
- case 2:
- n_amostras_new = 2;
- flag_erro = 0;
- break;
- case 4:
- n_amostras_new = 4;
- flag_erro = 0;
- break:
- case 8:
- n_amostras_new = 8;
- flag_erro = 0;
- break;
- case 16:
- n_amostras_new = 16;
- flag_erro = 0;
- break;
- case 32:
- n_amostras_new = 32;
- flag_erro = 0;
- break;
- case 64:
- n_amostras_new = 64;
- flag_erro = 0;
- break;
- default:
- flag_erro = 1;
- }
- }
- // se nº de amostras correcto...
- if ((buffer_rx[0] == 'N') && (flag_erro == 0)) {
- // transmite nº de amostras
- sprintf(buffer_tx, "N amostras = %d\n\r", n_amostras_new);
- transmite_buffer();
- }
- }
- int main(void) {
- inic();
- while (1) {
- // verifica switches
- switches = PINA & 0b00111111;
- switch (switches) {
- case 0b00111110:
- n_amostras_new = 1;
- break;
- case 0b00111101:
- n_amostras_new = 8;
- break;
- case 0b00111011:
- n_amostras_new = 16;
- break;
- case 0b00110111:
- n_amostras_new = 32;
- }
- // se e necessario nova aquisicao
- if (flag_aq) {
- soma_h = soma_l = 0;
- // inicializa numero de amostras
- n_amostras = n_amostras_new;
- n_amostras_bak = n_amostras_new;
- // inicio da primeira conversao
- ADCSRA |= 0x40;
- // reset da flag de aquisicao
- flag_aq = 0;
- }
- if (flag_end) {
- // calcula media em 16 bits
- media = (media_h << 8) + media_l;
- // calcula media em mV
- medida = (long int)media * 5000 / 1024;
- d_medida = medida;
- // extrai digitos
- digito[0] = d_medida / 10000;
- d_medida = d_medida % 1000;
- digito[1] = d_medida / 100;
- d_medida = d_medida % 100;
- digito[2] = d_medida / 10;
- digito[3] = d_medida % 10;
- // desactiva flag
- flag_end = 0;
- }
- // se recebeu comunicacao do exterior
- if (flag_rx == 1) {
- processa_rx();
- // desactiva flag
- flag_rx = 0;
- }
- }
- }
- // ficheiro assembly
- ; LEITURA DO ADC
- #define __SFT_OFFSET 0
- #include <interrupt.h>
- .global ler_AD
- .extern soma_l
- .extern soma_h
- .extern n_amostras
- .extern n_amostras_bak
- .extern media_h
- .extern media_l
- .extern flag_end;
- ler_AD:
- ; guarda registos
- push r0
- push r1
- push r2
- push r3
- push r16
- ; leitura do AD
- in r0, ADCL
- in r1, ADCH
- ; leitura da variavel soma (inteiro)
- lds r2, soma_l
- lds r3, soma_h
- ; soma valores
- add r2, r0
- adc r3, r1
- ; guarda resultado
- sts soma_l, r2
- sts soma_h, r3
- ; decrementa contador de amostras
- lds r0, n_amostras
- dec r0
- sts n_amostras, r0
- ; verifica se terminou as amostragens
- breq calc_media
- ; se nao terminou desencadeia nova aquisicao
- sbi ADCSRA, 6
- jmp f_ler_AD
- calc_media:
- ; se terminou, vai calcular media
- lds r0, n_amostras_bak
- shift:
- lsr r0
- breq f_shift
- clc
- ror r3
- ror r2
- jmp shift
- f_shift:
- ; guarda media
- sts media_h, r3
- sts media_l, r2
- ldi r16, 1
- ; activa flag aquisicao completa
- sts flag_end, r16
- f_ler_AD:
- ; recupera registos
- pop r16
- pop r3
- pop r2
- pop r1
- pop r0
- ret
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement