Ir ao conteúdo
  • Cadastre-se

edu.

Membro Pleno
  • Posts

    889
  • Cadastrado em

  • Última visita

Reputação

12
  1. A linguagem do compilador é, em si, a linguagem C básica. Qualquer livro de linguagem C servirá, mas recomento em especial o "The C Programming Language", dos próprios criadores da linguagem. Quanto ao compilador, se for no diretório do mesmo e entrar na pasta "docs", vais encontrar o manual do compilador, lá há todas as informações que precisas. Se buscares mais profundamente no google vais encontrar mais material de outras fontes, te recomendei os garantidos. OBS.: para programares com o CCS e meus códigos é preciso adaptar pois o CCS tem suas peculiaridades. ;]
  2. Me parece igual o comando de clr, e o outro não lembro a ordem dos bits mas também me parece igual. Procure o datasheet do teu display e compare com o normal, mas é quase certo que é igual, isso costuma seguir um padrão de interface. Já testastes na prática se funciona? Ou em algum simulador?
  3. Cara, para PICs 18f utilize o compilador MPLAB C18. Com um pouco de trabalho da pra converter aquelas minhas funções e já sair rodando. Não tem muito mistério, serial, LCD e teclado é tudo na base do que eu postei antes.
  4. Opa, Você tem dois caminhos para iniciar, programando em C ou em ASM. Se você já possuí uma base em C siga por ai que será mais fácil no começo, mas, depois de estar mais seguro recomendo que faça alguns programinhas em ASM para pegar mais o funcionamento interno do MCU e saber a fundo o que que é feito de modo a poder otimizar seu próprio código em C. Assim como todo mundo, inicie piscando LEDs e lendo botões. Baixe a IDE da Microchip, o MPLAB (eu estou acostumado com o MPLAB normal, tem o MPLAB X que eu nunca usei e não poderei te ajudar). Com a IDE você poderá programar em ASM. Se quiser em C, busque pelo compilador HI-TECH C, para PIC16. Estou supondo que você vai iniciar em C, tem algumas coisas que deves cuidar. No seu código deves incluir sempre o cabeçalho htc.h. Quando você cria o projeto e escolhe qual o PIC que vai usar há uma série de definições que são feitas. Esse cabeçalho se baseia nessas definições e inclui os cabeçalhos padrões com as funções básicas e os registradores do seu MCU. Depois deves definir a frequência do "cristal", que na verdade é a frequência do circuito oscilador, independente se for cristal ou não. Com base nessa sua definição o compilador vai poder calcular as funções de delay para gerar atrasos. Em seguida vem os configuration words, neles você vai fazer as configs mais básicas, eu recomendo tirar o MCLR, WDT e habilitar o PWRT. Por fim vem o main(), onde vais colocar o seu código. Tudo isso que eu falei e ainda mais está disponível no User Guide do HI-TECH, que se encontra na pasta do compilador em docs/manual.pdf (se estiver com o projeto aberto basta apertar F11). Poste ai o MCU e a linguagem que poderemos ajudar mais. Ah, estava me esquecendo, esse negócio de fazer na unha é relativo. Você vai encontrar códigos prontos para o PIC assim como os do arduino. Um exemplo é o que eu já postei, basta incluir o .c e definir os pinos que podes usar o LCD que funciona. PORÉM, creio que seja importante entender o que está por trás, uma vez que sabes como funciona o negócio, podes pegar um código pronto de qualquer procedência, dar uma lida, ajeitar para a sua aplicação e mandar bala. Mas antes tens que entender o que está acontecendo, para depois fazer isso. ;] Abraço, Eduardo.
  5. Opa, Se não me engano a diretiva WDTDIS era usada em versões anteriores do HI-TECH, atualmente usa-se o que coloquei nos exemplos. Para saber todos os registradores e definições disponíveis para seu MCU deves "seguir" os includes do compilador até achar o cabeçalho do seu PIC. Na pasta includes dentro da pasta do HI-TECH você encontra o arquivo pic.h, dentro dele há algumas definições e alguns includes, e você deve ir atras até chegar ao include do seu pic. Vai ser um arquivo do tipo picxxfxxx.h, mas lembrando que alguns MCUs compartilham o mesmo cabeçalho, então pode não haver o arquivo com o nome do seu PIC mesmo. O 16f690 é assim, não me lembro de cabeça qual o nome original, mas é um dos que são de sua familia, que estão juntos no datasheet. Abraço, desculpe o atraso.
  6. Boa noite, Sei muito pouco sobre processamento digital de sinais devido a matemática por trás dos filtros que ainda é muito avançada para mim. Conheço bastante da parte conceitual dos filtros e etc e estou bastante contente com esse tópico e curioso para aprender mais. Vou começar com uma pergunta que deve ser bastante simples, mas faz algum tempo que venho pensando nela. Sé é possível (através das transformadas) trazer um determinado sinal do domineo do tempo para o domineo da frequência, pode-se então fazer um filtro ideal zerando completamente a amplitude das frequências indesejadas? Parabéns pelo tópico e vamo que vamo.
  7. Opa, Adicionei sua contribuição ao sumário. Me parece que está faltando a função "Inicializacao()".
  8. Bom dia, não havia reparado que havia respostas neste tópico, desculpem. Com relação ao caso do ricardo, o pino RW seleciona se a operação a ser realizada será de leitura ou escrita, como na maioria dos casos não é necessário ler o que está escrito no LCD esse pino é ligado ao GND de modo que sempre sejam feitas operações de escrita. Se você deseja ler e escrever o conteúdo do LCD deve controlar esse pino para ter ambas as operações liberadas. As funções de copiar e colar são implementações do sistema operacional, que combinam o uso do teclado, mouse e monitor (que são a interface do computador) para interagir com o operador. Caso você deseje utilizar funções semelhantes deve desenvolver a própria interface utilizando o teclado referido e o LCD.
  9. Eu ja vi um projeto muito interressante que bolava um pequeno leitor de partitura de modo que reproduzia uma musica inteira. A jogada era uma string onde ficava a partitura, o pic lia a string e utilizava um timer para gerar a frequencia da nota e outro para gerar a base de tempo da musica. Ia trocando as notas e passando a musica. Você poderia utilizar esse principio para fazer isso, inicialmente com um buzzer normal (não auto-oscilante). Ele faz um barulho legal inicialmente para testes. Eu mesmo penso em reproduzir esse projeto mas ainda nao disponho de tempo para tanto. Se implementar algo assim basta gravaz várias strings com quantas musicas quiser e com dois botões voce seleciona a musica e bota pra tocar.
  10. Ja faz um tempinho que eu estou tentando concluir mais um pequeno código para contribuir ai, mas a pascoa me deu alguma folginha e consegui concluir. É uma biblioteca para rodar LCDs alfanuméricos, aqui em casa eu só tenho 16x2 e foi com o que testei, no proteus coloquei vários outros de diversos tamanhos e deu tudo certo também. O único porém é que com mais de duas linhas dai tem que fazer alguma adaptações e acertar os endereços iniciais das linhas no LCDGotoxy(). Sem mais delongas, o código eu fiz bastante simples com e sem opção de leitura baseando-me no datasheet do controlador HD44780U da HITACHI. Além do comum eu criei uma função para criar caracteres novos na CGRAM, e algumas funções definidas que facilitam no trabalho com cursor, shift de display e outros comandos básicos. * * * * * LCD DRIVER INCLUDE * * BY: EDUARDO T. LOURENÇO * * * * Code for PIC16 HI-TECH C compiler. * * v1.0.00 * * * * * ************************************************************************/ #ifndef _LCD_C_ #define _LCD_C_ /************************************************************************ * * * USEFUL DEFINITIONS * * * ************************************************************************/ #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif #ifndef _XTAL_FREQ #error "_XTAL_FREQ not defined." #endif /************************************************************************ * * * SYSTEM DEFINITIONS * * * * LCD_ENABLE_READS: * * TRUE * * Enable read operations in the display, RW pin should * * be connected and TRIS definition associated to data pins. * * FALSE * * Disable read operations in the display, RW pin should * * be connect to the ground. * * LCD_LINE1: * * Address number of the first line of the screen. * * LCD_LINE2: * * Address number of the second line of the screen. * * * ************************************************************************/ #define LCD_ENABLE_READS TRUE #define LCD_LINE1 0x80 #define LCD_LINE2 0xC0 /************************************************************************ * * * PIN DEFINITIONS * * * * In case of using RW pin, be sure that TRIS definition are * * matching the right IO pin. * * * ************************************************************************/ #define LCD_DB7 RC0 #define LCD_DB6 RC1 #define LCD_DB5 RC2 #define LCD_DB4 RC3 #define LCD_E RC4 #define LCD_RS RC5 #if LCD_ENABLE_READS == TRUE #define LCD_RW RC6 #define TRIS_DB7 TRISC0 #define TRIS_DB6 TRISC1 #define TRIS_DB5 TRISC2 #define TRIS_DB4 TRISC3 #endif /************************************************************************ * * * FUNCTION PROTOTYPES * * * ************************************************************************/ #if LCD_ENABLE_READS == TRUE char LCDReadNibble(void); #endif void LCDWriteNibble( char LCDWNnib ); #if LCD_ENABLE_READS == TRUE char LCDBusyAc(void); char LCDGetc(void); #endif void LCDWrite( char LCDWrs ,char LCDWdata ); void LCDPutc( char LCDPchar ); void LCDInit(void); void LCDPuts( const char * LCDPstr ); void LCDGotoxy( char LCDGx, char LCDGy ); void LCDMakeChar( char LCDMCaddr, const char *LCDMCdata ); /************************************************************************ * * * LCD_TRIS_READ * * * * Input: * * Void * * Return: * * Void * * Description: * * Setup data pins as inputs for read operations. * * * ************************************************************************/ #if LCD_ENABLE_READS == TRUE #define LCDTrisRead() { TRIS_DB7=1; TRIS_DB6=1; TRIS_DB5=1; TRIS_DB4=1; } #endif /************************************************************************ * * * LCD_TRIS_WRITE * * * * Input: * * Void * * Return: * * Void * * Description: * * Setup data pins as outputs for write operations. * * * ************************************************************************/ #if LCD_ENABLE_READS == TRUE #define LCDTrisWrite() { TRIS_DB7=0; TRIS_DB6=0; TRIS_DB5=0; TRIS_DB4=0; } #endif /************************************************************************ * * * LCD_READ_NIBBLE * * * * Input: * * Void * * Return: * * Char * * The nibble read from LCD in the 4 high order bits, * * the 4 low order bits are always 0. * * Description: * * Read a nibble from LCD. * * * ************************************************************************/ #if LCD_ENABLE_READS == TRUE char LCDReadNibble(void) { char LCDRNnib=0; LCD_E = 1; __delay_us(1); if( LCD_DB7 ) LCDRNnib |= 0x80; if( LCD_DB6 ) LCDRNnib |= 0x40; if( LCD_DB5 ) LCDRNnib |= 0x20; if( LCD_DB4 ) LCDRNnib |= 0x10; LCD_E = 0; __delay_us(1); return LCDRNnib; } #endif /************************************************************************ * * * LCD_WRITE_NIBBLE * * * * Input: * * LCDWNnib * * The nibble to be send, just the 4 high order bits are * * going to be send. * * Return: * * Void * * Description: * * Write a nibble in the LCD. * * * ************************************************************************/ void LCDWriteNibble( char LCDWNnib ) { LCD_E = 1; __delay_us(1); if( LCDWNnib&0x80 ) LCD_DB7 = 1; else LCD_DB7 = 0; if( LCDWNnib&0x40 ) LCD_DB6 = 1; else LCD_DB6 = 0; if( LCDWNnib&0x20 ) LCD_DB5 = 1; else LCD_DB5 = 0; if( LCDWNnib&0x10 ) LCD_DB4 = 1; else LCD_DB4 = 0; __delay_us(1); LCD_E = 0; } /************************************************************************ * * * LCD_BUSY_AC * * * * Input: * * Void * * Return: * * Char * * AC * * Address counter in the 7 low order bits. * * BUSY * * Busy flag in the MSB. * * Description: * * Read address counter and busy flag status. * * * ************************************************************************/ #if LCD_ENABLE_READS == TRUE char LCDBusyAc(void) { char LCDBAbusy; LCDTrisRead(); LCD_RS = 0; LCD_RW = 1; __delay_us(1); LCDBAbusy = LCDReadNibble(); LCDBAbusy |= LCDReadNibble()>>4; return LCDBAbusy; } #endif /************************************************************************ * * * LCD_GETC * * * * Input: * * Void * * Return: * * Char * * Character read from the LCD. * * Description: * * Reads a character from LCD DDRAM. * * * ************************************************************************/ #if LCD_ENABLE_READS == TRUE char LCDGetc(void) { char LCDGchar; LCDTrisRead(); LCD_RS = 1; LCD_RW = 1; __delay_us(1); LCDGchar = LCDReadNibble(); LCDGchar |= LCDReadNibble()>>4; while( LCDBusyAc()&0x80 ); return LCDGchar; } #endif /************************************************************************ * * * LCD_WRITE * * * * Input: * * LCDWrs * * TRUE * * A data is going to be write. * * FALSE * * A command is going to be write. * * LCDWdata * * Data or command that is going to be send. * * Return: * * Void * * Description: * * Write a data or command to the LCD. * * * ************************************************************************/ void LCDWrite( char LCDWrs ,char LCDWdata ) { if( LCDWrs ) LCD_RS = 1; else LCD_RS = 0; #if LCD_ENABLE_READS == TRUE LCD_RW = 0; LCDTrisWrite(); #endif __delay_us(1); LCDWriteNibble( LCDWdata ); LCDWriteNibble( LCDWdata<<4 ); #if LCD_ENABLE_READS == TRUE while( LCDBusyAc()&0x80 ); #else if( LCDWdata == 1 ) __delay_ms(2); else __delay_us(50); #endif } /************************************************************************ * * * LCD_COMMAND * * * * Input: * * LCDCcom * * Command to be send. * * Return: * * Void * * Description: * * Write a command to the LCD. * * * ************************************************************************/ #define LCDCommand(LCDCcom) LCDWrite(FALSE,LCDCcom) /************************************************************************ * * * LCD_PUTC * * * * Input: * * LCDPchar * * Character to be write on the LCD. * * Return: * * Void * * Description: * * Write a character to LCD DDRAM. * * * ************************************************************************/ void LCDPutc( char LCDPchar ) { if( LCDPchar == '\f' ) //form feed (FF) = 0x0C = '\f' LCDCommand( 0x01 ); else LCDWrite(TRUE,LCDPchar); } /************************************************************************ * * * LCD_INIT * * * * Input: * * Void * * Return: * * Void * * Description: * * Initialize the LCD. * * * ************************************************************************/ void LCDInit(void) { LCD_E = 0; LCD_RS = 0; #if LCD_ENABLE_READS == TRUE LCD_RW=0; #endif __delay_ms(50); LCDWriteNibble( 0x30 ); __delay_ms(5); LCDWriteNibble( 0x30 ); __delay_us(150); LCDWriteNibble( 0x30 ); LCDWriteNibble( 0x20 ); __delay_us(50); LCDCommand( 0x28 ); LCDCommand( 0x0F ); LCDCommand( 0x01 ); LCDCommand( 0x06 ); } /************************************************************************ * * * LCD_PUTS * * * * Input: * * LCDPstr * * Pointer to a string to be write. * * Return: * * Void * * Description: * * Puts a string on the LCD DDRAM, the string must ends with * * /0 (0x00); * * * ************************************************************************/ void LCDPuts( const char * LCDPstr ) { while( *LCDPstr ) { LCDPutc( *LCDPstr ); LCDPstr++; } } /************************************************************************ * * * LCD_GOTOXY * * * * Input: * * LCDGx * * X position (column). * * LCDGy * * Y position (line). * * Return: * * Void * * Description: * * Changes the cursor position to X, Y (starting at 0,0). * * * ************************************************************************/ void LCDGotoxy( char LCDGx, char LCDGy ) { if( LCDGy == 0 ) LCDGy = LCD_LINE1; else if( LCDGy==1 ) LCDGy = LCD_LINE2; LCDCommand( LCDGy + LCDGx ); } /************************************************************************ * * * LCD_MAKE_CHAR * * * * Input: * * LCDMCaddr * * DDRAM address of the new character (0 to 7). * * LCDMCdata * * Pointer to 8byte data string of the new character. * * Return: * * Void * * Description: * * Creates a new character at CGRAM. * * * ************************************************************************/ void LCDMakeChar( char LCDMCaddr, const char *LCDMCdata ) { char LCDMCaux; LCDCommand( 0x40 | ((LCDMCaddr&0x07)<<3) ); for( LCDMCaux=0; LCDMCaux<8; LCDMCaux++ ) LCDWrite( 1, LCDMCdata[LCDMCaux] ); LCDCommand( 0x80 ); } /************************************************************************ * * * USEFUL FUNCTIONS * * * ************************************************************************/ #define LCDClear() LCDCommand(0x01) #define LCDHome() LCDCommand(0x02) #define LCDDisplay(LCD_D) LCDCommand(0x08|LCD_D) #define DISPLAY_OFF 0x00 #define CURSOR_OFF 0x04 #define CURSOR_ON 0x06 #define CURSOR_BLINK 0x07 #define LCDShift(LCD_S) LCDCommand(0x10|LCD_S) #define MOVE_LEFT 0x00 #define MOVE_RIGHT 0x04 #define SHIFT_LEFT 0x08 #define SHIFT_RIGHT 0x0C #endif /************************************************************************ * * * * * LCD DRIVER END * * * * * ************************************************************************/ /************************************************************************ Junto aqui o pequeno aplicativo que rodei para os testes. #define _XTAL_FREQ 4000000 __CONFIG( WDTE_OFF & MCLRE_OFF & FOSC_INTRCIO & PWRTE_ON ); #include "lcd_character.c" char aux; const char data[8][8]={ {0x12,0x09,0x04,0x12,0x09,0x04,0x12,0x09}, {0x04,0x04,0x04,0x1F,0x04,0x04,0x04,0x00}, {0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09}, {0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04}, {0x1F,0x00,0x1F,0x00,0x1F,0x00,0x1F,0x00}, {0x1F,0x11,0x11,0x11,0x11,0x11,0x11,0x1F}, {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01}, {0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11} }; void main(void) { ANSEL = 0; ANSELH = 0; TRISA = 0; TRISB = 0; TRISC = 0; PORTA = 0; PORTB = 0; PORTC = 0; LCDInit(); LCDMakeChar( 0, data[0] ); LCDMakeChar( 1, data[1] ); LCDMakeChar( 2, data[2] ); LCDMakeChar( 3, data[3] ); LCDMakeChar( 4, data[4] ); LCDMakeChar( 5, data[5] ); LCDMakeChar( 6, data[6] ); LCDMakeChar( 7, data[7] ); LCDGotoxy(0,0); LCDPutc(0); LCDPutc(1); LCDPutc(2); LCDPutc(3); LCDPutc(4); LCDPutc(5); LCDPutc(6); LCDPutc(7); LCDGotoxy(2,1); LCDPuts("Hello World"); LCDGotoxy(6,1); aux = LCDGetc(); LCDGotoxy(15,1); LCDPutc(aux); while(1); } #include <htc.h> --------------------------------------------------------------------------------------------------------- Agora gostaria de saber um pouco do felipe_eletronic, nao entendi direito a organização que tu tinha proposto com as pastas e .c e .h, tirei uma SS do meu workspace para que possas entender como eu trabalho. Tentei adicionar o código no Source Files e deu erro.
  11. Opa, voltando ae para mais uma contribuição. Felipe, eu fiz como você disse para organizar o código mas o resultado final foi mais desordem do que ordem. Enfim, é muita coisa para cada arquivo criar um .h e depois criar sub-folders para os arquivos. Eu prefiro fazer um projeto simples, com o main na lista de arquivos e no topo do código adicionar os demais .c. Com o arquivo bem organizado e as descrições das funções claras é possível tornar o código bem legível. Enfim, pulando essa parte de organização do código e etc que é bastante pessoal de cada um, o real motivo que me trouxe aqui foi uma nova biblioteca bastante simples porém extremamente útil para lidar com a UART. Eu fiz as funções básicas para lidar com o hardware já pronto do MCU, inicialização e envio e recebimento de dados. Tentei por mais de uma vez implementar uma fifo de entrada e saída mais eficiente porém me perdi em erros e não consegui completar, cheguei a concluão que talvez não fosse tão útil para um driver genérico e que estivesse perdendo tempo. O driver tem ao final dois tipos de função, com e sem o controle de erros. Para aplicações bem simples (que são a maioria) e que a conversa é simples e não se precisa de demasiado controle fiz as funções de sempre Putc, Puts e Getc. Funcionam bem e quebram grande parte dos galhos. Porém quando é preciso tratar error e enviar dados com mais eficiência eu criei as funções PutByte e GetByte, que retornam erros para fazer o controle da porta, além de não ficarem trancadas aguardando a liberação do buffer. Penso eu que a interrupção é uma característica bem peculiar de cada código e que varia muito, logo não seriam realmente úteis funções para lidar com as ints. Por fim, na inicialização da porta eu fiz o cálculo do baud rate com contador de 16bits e high speed, pois oferece o maior 'range' de velocidades com maior resolução (precisão). * * * * * UART DRIVER INCLUDE * * BY: EDUARDO T. LOURENÇO * * * * Code for PIC16 HI-TECH C compiler. * * * * * ************************************************************************/ #ifndef _UART_C_ #define _UART_C_ /************************************************ * * * UART ERROR DEFINITION * * * * UART_SUCCESSFUL, no error has occured. * * UART_ERROR, an error has occured. * * UART_FRAMIN_ERROR, stop bit not recived. * * UART_OVERRUN_ERROR, byte recived without * * space in the buffer. * * UART_NO_DATA_AVAILABLE, there is no data * * on the recive buffer. * * * ************************************************/ #define UART_SUCCESSFUL 0 #define UART_ERROR 1 #define UART_FRAMING_ERROR 0x03 #define UART_OVERRUN_ERROR 0x05 #define UART_NO_DATA_AVAILABLE 0x09 /************************************************ * * * UART_INIT * * * * Input: Baud rate (24bits). * * Return: Error report. * * Description: Initializate the UART * * port in asynchronous mode for 8bits. * * * ************************************************/ bit UARTInit(unsigned short long UARTIbaud) { UARTIbaud = _XTAL_FREQ/(4*UARTIbaud); if( (UARTIbaud>1) && (UARTIbaud<65536) ) { BAUDCTL = 0x08; UARTIbaud --; SPBRG = UARTIbaud; SPBRGH = UARTIbaud >> 8; TXSTA = 0x24; RCSTA = 0x90; return UART_SUCCESSFUL; } else return UART_ERROR; } /************************************************ * * * UART_CLOSE * * * * Input: void. * * Return: void. * * Description: Close the UART port and * * reset the default values in registers. * * * ************************************************/ #define UARTClose() { RCSTA=0; TXSTA=0; BAUDCTL=0; SPBRG=0; SPBRGH=0; } /************************************************ * * * UART_RX_BUFFER * * * * Input: void. * * Return: 1 if there is a char in the * * recive buffer, else 0. * * Description: Reads the recive buffer * * status. * * * ************************************************/ #define UARTRxBuffer() ( RCIF ) /************************************************ * * * UART_TX_BUFFER * * * * Input: void. * * Return: 1 if there is a space in the * * transmit buffer, else 0. * * Description: Reads the transmit buffer * * status. * * * ************************************************/ #define UARTTxBuffer() ( TXIF ) /************************************************ * * * UART_GET_BYTE * * * * Input: Pointer to data storage. * * Return: Error report. * * Description: Gets the byte in the * * recive buffer (RXREG). * * * ************************************************/ char UARTGetByte(char *UARTGBdata) { char UARTGBreturn=UART_SUCCESSFUL; if( UARTRxBuffer() ) { if( FERR || OERR ) { if( FERR ) { UARTGBreturn = RCREG; UARTGBreturn = UART_FRAMING_ERROR; } if( OERR ) { CREN=0; CREN=1; UARTGBreturn |= UART_OVERRUN_ERROR; } } else *UARTGBdata = RCREG; } else UARTGBreturn = UART_NO_DATA_AVAILABLE; return UARTGBreturn; } /************************************************ * * * UART_PUT_BYTE * * * * Input: Byte to be send. * * Return: Error report. * * Description: Sends the desired byte * * to UART port. * * * ************************************************/ bit UARTPutByte(char UARTPBdata) { if( UARTTxBuffer() ) { TXREG = UARTPBdata; return UART_SUCCESSFUL; } else return UART_ERROR; } /************************************************ * * * UART_GETC * * * * Input: void. * * Return: Character in buffer. * * Description: Gets a character. * * * ************************************************/ char UARTGetc(void) { char UARTGchar; if( !UARTGetByte(&UARTGchar) ) return UARTGchar; else return 0; } /************************************************ * * * UART_PUTC * * * * Input: Character to be send. * * Return: void. * * Description: Sends a character. * * * ************************************************/ void UARTPutc(char UARTPchar) { while( UARTPutByte(UARTPchar) ); } /************************************************ * * * UART_PUTS * * * * Input: Pointer to string. * * Return: void. * * Description: Sends a string. * * * ************************************************/ void UARTPuts(const char *UARTPpointer) { while( *UARTPpointer ) { UARTPutc(*UARTPpointer); UARTPpointer++; } } #endif /************************************************************************ * * * * * UART DRIVER END * * * * * ************************************************************************/ /************************************************************************ Novamente segue um exemplo bem simples da utilização do driver. #define _XTAL_FREQ 4000000 #include "uart_asynchronous_8bits.c" __CONFIG( FOSC_INTRCIO & WDTE_OFF & PWRTE_ON & MCLRE_OFF ); void interrupt code(void) { UARTPutc(UARTGetc()); } void main(void) { ANSEL=0; ANSELH=0; UARTInit(9600); RCIE=1; PEIE=1; GIE=1; UARTPuts("Init OK!"); while(1) { NOP(); } } #include <htc.h>
  12. Duas dúvidas: Se o .c inclui o .h no main devo incluir o .c, correto? Como assim compilar a pasta? ps.: vi no outro tópico seu a opinião, concordo com você!
  13. Hmm... Nunca fui atras das bibliotecas do CCS, alguns drivers eu sei que sao abertos, mas as funções nativas não. No HI-TECH eu encontrei vários cabeçalhos onde ele descreve e declara a função, mas o código em si não encontrei. Também n fui muito atras. Como mostrei acima prefico criar meus proprios drivers. O negócio do HI-TECH são os exemplos mais para frente, as application notes e todo o duporte do fabricante. Além de como disse, ter o hardware todo declarado e aberto para manipular.
  14. O problema é que no CCS você perde o controle do hardware, não sabe o que vai ser gerado a cada linha e nao tem acesso a todos os registradores do MCU. Para se utilizar ele quase sempre é necessário mapear algum registrador que precise, além de que, quando os bugs aparecem, tem que esquentar muito a cabeça para procurar as falahas pois tudo é feito por bibliotecas prontas e não se sabe o que ta rolando no hardware. Programação em C é bastante simples, você ja programou em assembly? É recomendado que se começe por ai para ter noção do que acontece por trás das linhas. Quando se entende o funcionamento do hardware o C é mais poderoso e oferece recursos muito além do ASM. Uma das vantagens é que o HI-TECH é compatível com ANSI-C, que é uma norma que define como as coisas devem ser, funçoes, macros, tipos de dados. Sendo assim, é bem mais fácil migrar do HI-TECH para outros compiladores, e inclusive para outros MCU uma vez que a norma é a mesma para todos. CCS é um pseudo ANSI, nao é compativel na maioria das coisas e tudo que você faz é indireto através de funçoes. Para iniciar, é bom utilizar LEDs e fazer piscas e leitura de estados de botões. Basicamente você precisa incluir o cabeçalho padrão <htc.c> que busca nas definições do projeto qual MCU estás utilizando e inclui o cabeçalho adequado. Quando se deseja utilizar delays defina a frequência do sistema _XTAL_FREQ. E antes de qualuqer código sete os bits de configuração com a função __CONFIG. As opções de configuração assim como o mapeamento de toda a memória do MCU estão no headrer .h do pic correspondente. Procure na pasta include pelo cabeçalho de seu MCU. Depois adicione o main e só botar pra rodar. O manual é mais uma fonte de consulta para que você possa ver os tipos de dados, os macros e funções que ele disponibiliza, não tem um bom "getting started". Espero que não desista e siga tentando com o HI-TECH, é um ótimo compilador e lhe trará os frutos do seu esforço em performace e economia. Sem falar que é free, do fabricante do MCU e com suporte de demais usuários e dos staffs no fórum da microchip (apesar de eu achar as respostas muito lentas e o apoio muito fraco).
  15. Boa noite a todos os companheiros do fórum! O que me trouxe aqui hoje foi a vontade de criar um tópico comum de livre acesso com material disponível para os amantes desse ótimo compilador da microchip. Em primeiro lugar gostaria de ressaltar que já utilizei o CCS e o ganho em liberdade e eficiência se comparado aos compiladores da microchip é imenso. A maioria dos iniciantes prefere esse compilador pela facilidade que as bibliotecas prontas oferecem, e na intenção de quebrar esse paradigma que inicio esse tópico. Ao longo do ano passado eu sesenvolvi por conta alguns "drivers" que usava para fazer a maioria dos meus programas. Para quando precisar da serial simplesmente usar "UARTInit(2400)", e pronto. Agora estou revisando eles em busca de erros e tentando torná-los mais eficientes, além de aplicar alguns conceitos de "boa programação" para tornar o código legível e facilmente adaptável para as mais diversas aplicações. --SUMÁRIO Teclado matricial - edu. UART - edu. LCD de caracteres - edu. Shift Register - ricardospimentel O primeiro arquivo que converti foi o driver para teclados matriciais digitais, fazendo a leitura por varredura. Antigamente eu utilizava delays e aguardava o pressionamento do botão para retornar valor. Agora procuro sempre que possível utilizar o loop principal do programa ininterrupto, de modo que seja executado rapidamente sem ficar preso por nada, assim pode-se adicionar um WatchDog dando mais segurança ao aplicativo sem que haja erros e resets indesejados durante delays e pressionamento de botões. Além disso implementei um buffer FIFO para as teclas lidas, assim, se por algum motivo o processamento dos digitos teclados for lento os mesmos serão armazenados para evitar perdas. Como disse acima, o buffer tem o tamanho definido pelo usuário para ser adaptável. Para finalizar antes de postar o código, eu escrevi os comentários e o código todo em inglês. Como quase todo material disponível por ai é na língua materna dos µC optei por utilizar também. Não sou nativo e provavelmente haverá erros nos comentários, me avisem para que possa arrumar. E é claro, fiquem livres para postar seus códigos e facilitar a vida de todos que utilizam o compilador. * * * * * KEYPAD DRIVER INCLUDE * * BY: EDUARDO T. LOURENÇO * * * * Code for PIC16 HI-TECH C compiler. * * * * * ************************************************************************/ #ifndef _KEYPAD_C_ #define _KEYPAD_C_ /************************************************ * * * PINOUT DEFINITION * * * * Columns input with pull-up. * * Lines push-pull output. * * * ************************************************/ #define PAD_C1 RC0 #define PAD_C2 RC1 #define PAD_C3 RC2 #define PAD_L1 RC3 #define PAD_L2 RC4 #define PAD_L3 RC5 #define PAD_L4 RC6 /************************************************ * * * SYSTEM DEFINITIONS * * * * PAD_BUFFER_SIZE, defines the size of * * the input buffer. * * PAD_LIMIT_FLAG, defines the number of * * bytes necessary to set the buffer flag. * * PAD_DEBOUNCE_LOOPS, defines the number * * of loops to debounce the pads. * * PAD_BUFFER_EMPTY, defines the error * * code when a getc is called with an empty * * buffer. * * PAD_DATA_INVALID, defines the value * * when an error occure while reading the * * keypad. * * * ************************************************/ #define PAD_BUFFER_SIZE 2 #define PAD_LIMIT_FLAG 1 #define PAD_DEBOUNCE_LOOPS 500 #define PAD_BUFFER_EMPTY 0 #define PAD_DATA_INVALID 0 /************************************************ * * * RETURN DEFINITIONS * * * * Return must be diffrent from * * PAD_BUFFER_EMPTY and PAD_DATA_INVALID. * * * ************************************************/ #define PAD_L1C1 '1' #define PAD_L1C2 '2' #define PAD_L1C3 '3' #define PAD_L2C1 '4' #define PAD_L2C2 '5' #define PAD_L2C3 '6' #define PAD_L3C1 '7' #define PAD_L3C2 '8' #define PAD_L3C3 '9' #define PAD_L4C1 '*' #define PAD_L4C2 '0' #define PAD_L4C3 '#' /************************************************ * * * GLOBAL VARIABLES * * * ************************************************/ unsigned int PADdebounce=0; char PADbuffer[PAD_BUFFER_SIZE],PADbufferCont=0; bit PADtaskStep=0; /************************************************ * * * PAD_TASKS * * * * Input: void. * * Return: void. * * Description: This function must be * * called periodicaly to keep the buffer * * updated. * * * ************************************************/ void PADTasks(void) { if( !PADtaskStep ) {//run step 0 PAD_L1=0; PAD_L2=0; PAD_L3=0; PAD_L4=0; __delay_us(1); if( !( PAD_C1 && PAD_C2 && PAD_C3 ) ) {//if pad is pressed if( PADdebounce > PAD_DEBOUNCE_LOOPS ) {//if debounce is done PADdebounce=0; if( PADbufferCont < PAD_BUFFER_SIZE ) {//if there is space in the buffer //check line 1 PAD_L2=1; PAD_L3=1; PAD_L4=1; __delay_us(1); if( !PAD_C1 ) PADbuffer[PADbufferCont] = PAD_L1C1; else if( !PAD_C2 ) PADbuffer[PADbufferCont] = PAD_L1C2; else if( !PAD_C3 ) PADbuffer[PADbufferCont] = PAD_L1C3; else {//check line 2 PAD_L1=1; PAD_L2=0; __delay_us(1); if( !PAD_C1 ) PADbuffer[PADbufferCont] = PAD_L2C1; else if( !PAD_C2 ) PADbuffer[PADbufferCont] = PAD_L2C2; else if( !PAD_C3 ) PADbuffer[PADbufferCont] = PAD_L2C3; else {//check line 3 PAD_L2=1; PAD_L3=0; __delay_us(1); if( !PAD_C1 ) PADbuffer[PADbufferCont] = PAD_L3C1; else if( !PAD_C2 ) PADbuffer[PADbufferCont] = PAD_L3C2; else if( !PAD_C3 ) PADbuffer[PADbufferCont] = PAD_L3C3; else {//check line 4 PAD_L3=1; PAD_L4=0; __delay_us(1); if( !PAD_C1 ) PADbuffer[PADbufferCont] = PAD_L4C1; else if( !PAD_C2 ) PADbuffer[PADbufferCont] = PAD_L4C2; else if( !PAD_C3 ) PADbuffer[PADbufferCont] = PAD_L4C3; else PADbuffer[PADbufferCont] = PAD_DATA_INVALID; } } } if( PADbuffer[PADbufferCont] != PAD_DATA_INVALID ) {//if data is valid PADbufferCont++; } } //goto step 1 PADtaskStep=1; } else//if debounce not done PADdebounce++; } else//if pad not pressed PADdebounce=0; } else {//run step 1 PAD_L1=0; PAD_L2=0; PAD_L3=0; PAD_L4=0; __delay_us(1); if( PAD_C1 && PAD_C2 && PAD_C3 ) {//if pad keep pressed if( PADdebounce > PAD_DEBOUNCE_LOOPS ) {//if debounce is done PADdebounce=0; //back to step 0 PADtaskStep=0; } else//if debounce not done PADdebounce++; } else//if pad not pressed PADdebounce=0; } //end pad_tasks } /************************************************ * * * PAD_KBHIT * * * * Input: void. * * Return: bit indicating if the buffer * * reach the defined number of chars or not. * * Description: Indicate the buffer * * status. * * * ************************************************/ bit PADKbhit(void) { if( PADbufferCont >= PAD_LIMIT_FLAG ) return 1; else return 0; } /************************************************ * * * PAD_GETC * * * * Input: void. * * Return: the oldest char in the buffer. * * Description: Read data from buffer. * * * ************************************************/ char PADGetc(void) { char PADGaux,PADGret; if( PADbufferCont ) { PADGret = PADbuffer[0]; for( PADGaux=0; PADGaux<PADbufferCont; PADGaux++ ) PADbuffer[PADGaux] = PADbuffer[PADGaux+1]; PADbufferCont--; return PADGret; } else return PAD_BUFFER_EMPTY; } /************************************************ * * * PAD_CLR * * * * Input: void. * * Return: void. * * Description: Clears the buffer. * * * ************************************************/ #define PADClear() PADbufferCont=0 /************************************************ * * * PAD_GET_NEXT_CHAR * * * * Input: void. * * Return: the next char pressed. * * Description: Clears the buffer, and * * gets the next char. * * * ************************************************/ char PADGetNextChar(void) { PADClear(); while( !PADbufferCont ) PADTasks(); PADClear(); return PADbuffer[0]; } #endif /************************************************************************ * * * * * KEYPAD DRIVER END * * * * * ************************************************************************/ /************************************************************************ EDIT: Segue um dos códigos que utilizei para fazer os testes e ajustes no driver. É bem simples e utiliza a UART na mão porque ainda não concluí a revisão dessa biblioteca (2400bps). #define _XTAL_FREQ 4000000 #include "keypad_3x4_digital.c" __CONFIG( FOSC_INTRCIO & WDTE_OFF & PWRTE_ON & MCLRE_OFF ); char aux; void main(void) { ANSEL = 0; ANSELH = 0; TRISA = 0; TRISB = 0; TRISC = 0x07; //RC0 to RC2 input PORTA = 0; PORTB = 0; PORTC = 0; TXSTA = 0x20; RCSTA = 0x90; BAUDCTL = 0; SPBRG = 25; SPBRGH = 0; while(1) { PADTasks(); // if( PADKbhit() ) // RA0=1; // else // RA0=0; // if( PADbufferCont == 2 ) // RA1=1; // else // RA1=0; // if( PADbufferCont > 2 ) // RA2=1; // else // RA2=0; if( PADKbhit() ) { TXREG = PADGetc(); // aux = PADGetc(); // if( aux=='1' ) // PORTA ^= 0x01; // else if( aux=='2' ) // PORTA ^= 0x02; // else if( aux=='3' ) // PORTA ^= 0x04; // else if( aux=='4' ) // PORTA ^= 0x10; // else if( aux=='5' ) // PORTA ^= 0x20; // else if( aux=='6' ) // PORTB ^= 0x10; // else if( aux=='7' ) // PORTB ^= 0x20; // else if( aux=='8' ) // PORTB ^= 0x40; // else if( aux=='9' ) // PORTB ^= 0x80; } } } #include <htc.h>

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...