"My software never has bugs. It just develops random features."
-Unknown
A idéia nessa página é focalizar programação em ANSI C, C para microcontroladores, C para rotinas gráficas, comunicação serial ou ethernet.
Antes de mais nada. Eu encontrei um tutorial sobre comunicação serial e comecei a alterar o código. Notei que é tão simples quanto usar a API do Java com a vantagem de ser C. Só que o código só funciona usando o compilador da Microsoft. Aqui pode ser encontrada a apostila do Professor Constantino. Há alguns trechos que precisam ser corrigidos no código original. A idéia é usar as funções para inicializar a porta serial e depois usar a função de leitura para fazer polling.
/* **************************************************************************** SOFTWARE PARA CONFIGURAÇAO DA PORTA SERIAL COMUNICAÇÃO SERIAL-UFMG AUTOR: PROFESSOR DR.CONSTANTINO SEIXAS FILHO, (UFMG) ALTERAÇÕES: DANIEL V. GOMES **************************************************************************** [DISCLAIMER]: Apesar de compreender todo esse código e ser capaz de ensiná-lo e usá-lo em aplicações reais, não me autorgo a autoria de seu cerne. Apenas o modifiquei. Quaisquer dúvidas: zlogdan@gmail.com. **************************************************************************** comentários Daniel V. Gomes estão entre tags <da></da> ou em LETRAS MAIUSCULAS */ #include <windows.h> #include <stdio.h> /*<da>VARIAVEIS GLOBAIS,</da>*/ DCB dcb;//<da>estrutura para configurar parametros de com.</da> HANDLE hCom;//<da>estrutura para configurar com.</da> BOOL fSuccess;// <da>FALSE = Não pode estabelecer com</da> . // <da>TRUE = Pode estabelecer com.</da> DWORD dwRead;//<da>N.o de bytes lidos </da> BOOL fWaitingOnRead = FALSE;//<da>FALSE = leitura pendente</da> //<da>TRUE = leitura habilitada</da> char *lpBuf;//<da></da> OVERLAPPED osReader = {0};//<da></da> DWORD dwRes;//<da></da> /*TIMEOUT*/ #define READ_TIMEOUT 500 /*ROTINA PARA INICIALIZAR A PORTA*/ BOOL InicializarPorta( char * ); /*ROTINA DE LEITURA*/ BOOL ReadStuff(); /*ROTINA DE ESCRITA*/ void WriteStuff(); void TrateLeituraComSucesso(char * lpBuf, DWORD dwRead);
/* **************************************************************************** SOFTWARE PARA CONFIGURAÇAO DA PORTA SERIAL COMUNICAÇÃO SERIAL-UFMG AUTOR: PROFESSOR DR.CONSTANTINO SEIXAS FILHO, (UFMG) ALTERAÇÕES: DANIEL V. GOMES **************************************************************************** [DISCLAIMER]: Apesar de compreender todo esse código e ser capaz de ensiná-lo e usá-lo em aplicações reais, não me autorgo a autoria de seu cerne. Apenas o modifiquei. Quaisquer dúvidas: zlogdan@gmail.com. **************************************************************************** comentários Daniel V. Gomes estão entre tags <da></da> ou em LETRAS MAIUSCULAS */ #include "serial.h" /*IMPLEMENTACÕES*/ BOOL InicializarPorta( char * COMPORTA ){ char *pcCommPort = COMPORTA ; hCom = CreateFile( pcCommPort, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if ( hCom == INVALID_HANDLE_VALUE ) { return FALSE; /*erro*/ }; fSuccess = GetCommState( hCom,&dcb ); if (!fSuccess ) { return FALSE ; /*Erro*/ }; dcb.BaudRate = CBR_9600; dcb.ByteSize = 8; dcb.Parity = NOPARITY; dcb.StopBits = ONESTOPBIT; fSuccess = SetCommState( hCom, &dcb ); if (!fSuccess ) { return FALSE; /*erro*/ }; return TRUE; } BOOL ReadStuff(){ osReader.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); /* <da> typedef struct _OVERLAPPED { DWORD Internal; DWORD InternalHigh; DWORD Offset; DWORD OffsetHigh; HANDLE hEvent;<==== } OVERLAPPED;</da> */ if ( osReader.hEvent == NULL ) { /*erro ao criar evento de leitura*/ return FALSE; }; /*Nenhuma leitura pendente*/ /* <da> ReadFile(...) inicializa a estrutura lPBuf um char de tamanho 32 bytes</da> */ if (!fWaitingOnRead ) { /*leitura*/ if (!ReadFile( hCom, lpBuf, 32, &dwRead, &osReader) ) // lpOverlapped { if (GetLastError()!= ERROR_IO_PENDING){ // Leitura não foi enfileirada // Erro de comunicação: relate-o } else { fWaitingOnRead = TRUE; // ativa flag leitura pendente } } } else { TrateLeituraComSucesso(lpBuf, dwRead); /* <da> Aqui os dados lidos lpBuf podem ser processados lpBuf é um char</da> */ }; /* <da> Supomos nesse caso que exista uma leitura pendente e que deve acontecer antes da leitura atual. O código espera 500 ms para em seguida verificar o status num laco switch </da> */ if (fWaitingOnRead) { // Existe uma leitura pendente: espere-a dwRes = WaitForSingleObject(osReader.hEvent, READ_TIMEOUT); /* <da>aguarda com timeout = 500 ms</da> */ /* OS COMENTARIOS DO PROFESSOR EXPLICAM BEM O QUE ACONTECERÁ. */ switch (dwRes) { // Leitura completada case WAIT_OBJECT_0: if (!GetOverlappedResult(hCom, &osReader, &dwRead, FALSE) ){ // Erro de comunicação: relate-o } else { // Leitura completada com sucesso TrateLeituraComSucesso(lpBuf, dwRead); } // Reseta flag para que outra operação possa ser iniciada fWaitingOnRead = FALSE; break; case WAIT_TIMEOUT: // Operação ainda não foi completada. Pode-se reemitir o comando e // continuar esperando ou cancelá-lo. // Este é um bom momento para realizar alguma outra atividade. break; default: // Erro em WaitForSingleObject; aborte. // Isto indica algum problema com o handle do evento na estrutura // OVERLAPPED. break; } } CloseHandle(osReader.hEvent); return TRUE; } void TrateLeituraComSucesso( char * lpBuf, DWORD dwRead ){ //com uma string lpBuf voce pode tratar os dados lidos } void WriteStuff(){ //Ainda precisa ser implementada... }
Estou meio com preguiça de escrever, mas o programa abaixo exemplifica e mostra como usar ponteiros com tipos de dados char, int e como passar ponteiros pra funções, alocar memória dinâmicamente pra um ponteiro e depois como usar esse ponteiro como um Array simples. Note que o operador & não é necessário quando passamos um char ou um ptr que representa um array para uma função.
#include <stdio.h> #include <stdlib.h> /*Receives a char pointer as parameter*/ void StuffWChars( char * ); /*Replace two strings*/ char *Reprace( char * , char * ); /*Replace two ints*/ void Swapnums( int * , int * ); /*Allocates memory for n int memory positions*/ int * myAloc ( int ); void PPtr2F( int * , int ); #define N = 10 int main(void) { /*Variables declaration*/ char ovo[] = "Ovo"; char *povo = "ovo"; int a = 2; int b = 3; int n ; int i; int * myinptr; /*End of Variables declaration*/ printf("[First we create two chars using two different methods...]\n"); printf("The string created as a char pointer: \n"); printf(">_ %s\n",povo); printf("The string created as an array of chars: \n"); printf(">_ %s\n",ovo); StuffWChars(povo); printf("\n\n"); printf("[Now let's us test a swap function...]\n"); char *Jaca = "Jaca"; char *Manga = "Manga"; char *tempo; printf("Before the change Jaca points to : %s\n",Jaca); tempo = Reprace( Jaca, Manga ); printf("After the change Jaca now points to : %s\n\n\n",tempo); printf("[Now let's us investigate numbers rather than chars...]\n"); Swapnums( &a, &b ); printf("\n\n"); printf("[Now let's us investigate passing pointers to functions...]\n"); n = 10; myinptr = myAloc( n ); for ( i = 0 ; i < 10 ; i++ ) { myinptr[i] = i - 1 ; }; PPtr2F( myinptr , n ); system("PAUSE"); return 0; } void StuffWChars( char * s ) { printf("the string passed to the function: \n"); printf(">_ %s\n",s); } char *Reprace( char * s1 , char * s2 ) { char *temp; temp = s1; s1 = s2; s2 = temp; printf("Jaca after reprace: \%s\n", s1); printf("Manga after reprace: \%s\n", s2); return s1; } void Swapnums( int * a , int * b ) { int temp; printf("The value of a before swapping was %d\n", *a ); printf("The value of b before swapping was %d\n", *b ); temp = *a; *a = *b; *b = temp; printf("The value of a after swapping was %d\n", *a ); printf("The value of b after swapping was %d\n", *b ); } int * myAloc ( int a ) { int * ptr; /* Does not need the cast in the ANSI C 99*/ ptr = ( int *)calloc( a , sizeof(int)); if (!ptr) { printf("Erro."); return 0; } else { return ptr;/*Note that we don't actually need to use the * operator. Horrors and terrors huh?*/ } } void PPtr2F( int * ptr, int n ) { int i ; i = 0; for ( i = 0 ; i < n ; i++ ) { if ( (ptr[i]==0) | (ptr[i]<0) ) { printf("%d\n",ptr[i]+20); } else { printf("%d\n",ptr[i]-3); } } }
A idéia é gerar vetores do tipo float dinâmicamente e passar esses valores para um arquivo .dat.
#include <stdio.h> #include <stdlib.h> /*THIS PROGRAM IS NOT COPYRIGHTED, I JUST GO AND TYPE, IF YOU USE IT, I HOPE IT HELPS YOU.*/ #include <stdio.h> #include <stdlib.h> #include <math.h> float *ptrX; float *ptrY; float *ptrM; /* Computes the modulus of a complex number */ float ObterModulo( float , float ); /* Allocates memoroy for an array of floats with size a */ float * myAloc ( int ); void InitPontos( int ); void LiberaMemoria(void); void WriteData2File( float *, float *, float *, int ); int main( void ) { InitPontos( 20 ); WriteData2File(ptrX,ptrY,ptrM,20); LiberaMemoria(); system("PAUSE"); return 0; } /* Implementations: */ void WriteData2File( float * ptrx, float *ptry, float *ptrM, int N ){ FILE *mfile; int i; float temp1,temp2,temp3; if ( ( mfile = fopen("Dados.dat","w") ) == NULL) { printf("Erro"); } else { for ( i = 0 ; i < N ; i++ ){ temp1 = ptrx[i];temp2=ptry[i];temp3=ptrM[i]; printf( "%f,%f,%f\n", temp1,temp2,temp3 ); fprintf( mfile , "%f %f %f\n", temp1,temp2,temp3); } fclose(mfile); } } float ObterModulo( float x , float y ){ return sqrt ( pow( x , 2 ) + pow ( y , 2 ) ); } float * myAloc ( int a ) { float * ptr; ptr = ( float *)calloc( a , sizeof(float)); if (!ptr) { printf("Erro."); return 0; } else { return ptr; } } void InitPontos( int N ){ int i; ptrX = myAloc( N ); ptrY = myAloc( N ); ptrM = myAloc( N ); for ( i = 0 ; i < N ; i++ ) { ptrX[i] = (float)(2.2*i + i); ptrY[i] = (float)(2.3*i); ptrM[i] = ObterModulo( ptrX[i] , ptrY[i] ); } } void LiberaMemoria(void){ free (ptrX); free (ptrY); free (ptrM); }
Como alocar memória dinamicamente em C usando calloc().
/* This program examplifies the use of calloc to allocate memory dinamically to a int array. Let's us let it clear this is not C++ just plain and good ol' C! */ #include <stdio.h> #include <stdlib.h> int * myAloc ( int );/*Declare the prototype to the function it returns a pointer to an int */ int main( void ) { int i; int *myptr;/*this is actually our dynamic structure*/ int a = 0; /*Say we are only now aware that we know the size of the sctruture, say the user typed the size of a data collection...*/ printf("Type the dimension of the array to be allocated: "); scanf("%d",&a); printf("\n"); myptr = myAloc( a ); /*Note that we don't use the * operator here which is not required. But we allocated memory*/ printf("Allocated memory for %d",a); printf(" numbers\n"); for ( i = 0 ; i < a ; i++ ){ myptr[i] = i; /*Now myptr is an array*/ } free ( myptr );/*Now that we aren't using memory it is always best to release it for all good..*/ system("Pause"); return 0; } /*Now we must implement myAloc to dynammically allocate memory for an array with size a */ int * myAloc ( int a ) { int * ptr; ptr = ( int *)calloc( a , sizeof(int)); if (!ptr) { printf("Erro."); return 0; } else { return ptr;/*Note that we don't actually need to use the * operator. Horrors and terrors huh?*/ } }
Eu estava pensando em bibliotecas gráficas e do nível de complexidade envolvido. E comecei a imaginar uma função hipotética que escreve um pixel na tela com uma cor determinada e partir disso estou escrevendo uma biblioteca hipotética em C puro. Sem trocadilho, por pura diversão.
/* **************************************************************** Theoretical C Program to create a theoretical C graphic library **************************************************************** author: Daniel Vasconcelos Gomes email: zlogdan@gmail.com **************************************************************** Comments: **************************************************************** It is fun to do, isn't it? It is getting less theoretical every day as I progress towards a more real-world solution. **************************************************************** */ #include <stdio.h> #include <conio.h> struct point { int x; int y; }; /*I couldn't avoid two typedefs here ;-)*/ typedef struct point point; typedef unsigned char uchar; void DrawALine( uchar Col, point *po , point *pf); void DrawACircle( uchar Col , point *p, int * R ); void DrawARectangle( uchar Col, point *po , point *pf); void DrawAPoligon( uchar Col, point *po, point *pf ); int ReturnScreenLength(); int ReturnScreenWidth(); int checksForValidPoints( point *po, point *pf ); /*Main Function*/ int main() { return 0; } /* This functions checks if the user provided a valid point, i.e. , if it is located within the current screen. */ int checksForValidPoints( point *po, point *pf ) { if ( pf->x >= ReturnScreenWidth() & pf->y >= ReturnScreenLength() ){ if ( po->y >= 0 & po->x >= 0 ) { return 1; } } else { return 0 ; } } /* This function creates a line by connection two points */ void DrawALine( uchar Col, point *po , point *pf ) { int i = 0; int j = 0; if ( checksForValidPoints( po, pf ) == 1 ){ /* Implementation, two valid points always connect a line. */ for ( i = po->x ; i < pf->x ; i++ ) { for ( j = po->y ; j < pf->y ; j++ ) { /*here goes the code to write pixels*/ } } /* End of main inplementation */ } else { printf("Can't do it man!"); } } /* This function creates a circle by connecting points around a central point with ratio R */ void DrawACircle( uchar Col, point *p, int * R ) { if ( checksForValidPoints( p , p ) == 1 ){ /* Here must go the code to draw the circle around point p with ratio R */ } else { printf("Can't do it man!"); } } /* This function creates a square by connecting two points. It will check if the points represent a valid square */ void DrawARectangle( uchar Col, point *po , point *pf ) { if ( checksForValidPoints( po , pf ) == 1 ){ /* Here must go the code to draw the rectangle on point po and p1 . */ } else { printf("Can't do it man!"); } } /* This function creates a square by connecting two points. It will not heck if the points represent a valid square as it will simply connect everything. */ void DrawAPoligon( uchar Col, point *po, point *pf ) { } /* It returns the length of the current screen. I don't know how to get the Screen length. */ int ReturnScreenLength() { return 1024; } /* It returns the Width of the current screen. I don't know how to get the Width length */ int ReturnScreenWidth() { return 728; }