Ir ao conteúdo
  • Cadastre-se

Programação PIC no CCS


Ivan (eletronic)

Posts recomendados

Galera estou fazendo melhorias num sistema que fiz a algum tempo e estou precisando que o PIC16f628 faça a oscilação de dois pinos em 50khz para excitar os drivers de uma fonte, porém isso sem que o programa normal pare de executar.

Ja disseram para eu usar o timer0 mas não sei e não estou encontrando material que me permita fazer tala aplicação.

Se necessario eu gosto o codigo que tenho ate o momento.

Grato

Link para o comentário
Compartilhar em outros sites

#include <16F628A.H>
#use delay(clock=4000000)
#fuses nowdt, nobrownout, nolvp, mclr, put, intrc, noprotect
#byte RA=0x05
#byte RB=0x06

#include "c:\Flex_lcd.c"

#define gravar_tela 10// o numero é o local de memoria
#define gravar_ste 11

#bit D1=rb.0
#bit D2=rb.1
#bit D3=rb.2
#bit D4=rb.3
#bit D5=ra.2
#bit D6=ra.3
#bit D7=ra.4

#bit TELA=ra.1
#bit BZ= ra.0
#bit STE=rb.7

#bit STEon=ra.7
#bit TELAon=ra.6

#bit f1=rb.5
#bit f2=rb.4
#bit TE=rb.6

unsigned long int valor;
unsigned int32 tensão;

unsigned long int mil;
unsigned long int cem;
unsigned long int cem1;
unsigned long int dez;
unsigned long int dez1;
unsigned long int uni;

int out1;//tela
int out2;//ste

int gravar_tela;//variaveis para gravação
int gravar_ste;

main()

{
valor=0, tensão=0, mil=0, cem=0, cem1=0, dez=0, dez1=0, uni=0, out1=0, out2=0;
BZ=0;
f1=0,f2=0;

write_configuration_memory(gravar_tela,TELA); //configurando memoria eeprom
write_configuration_memory(gravar_ste,STE);

set_tris_a(0b11011100);
set_tris_b(0b00001111);


lcd_init();
lcd_putc(" inicio"); //criar nome fantasia
lcd_gotoxy(1,2); //Inicialização segunda linha
lcd_putc(" Controlador HE1");

delay_ms(2000);

TELA = read_EEPROM (gravar_tela); //lendo memoria eeprom
STE = read_EEPROM (gravar_ste);




loop:

if(D7==1)delay_ms(1);
if(D7==1)valor=valor+128;
if(D6==1)delay_ms(1);
if(D6==1)valor=valor+64;
if(D5==1)delay_ms(1);
if(D5==1)valor=valor+32;
if(D4==1)delay_ms(1);
if(D4==1)valor=valor+16;
if(D3==1)delay_ms(1);
if(D3==1)valor=valor+8;
if(D2==1)delay_ms(1);
if(D2==1)valor=valor+4;
if(D1==1)delay_ms(1);
if(D1==1)valor=valor+2;


tensão=valor*196078;//tentar usar 585937 para 15 volts
tensão=tensão/10000;

if(tensão==4999)tensão=5000;//modificar

mil=tensão/1000;
cem=tensão-(mil*1000);
cem1=cem/100;
dez=tensão-(mil*1000)-(cem1*100);
dez1=dez/10;
uni=tensão-(mil*1000)-(cem1*100)-(dez1*10);

lcd_gotoxy(11,2);

lcd_putc(0x30+mil);
lcd_putc(".");
lcd_putc(0x30+cem1);
lcd_putc(0x30+dez1);
lcd_putc(0x30+uni);
lcd_putc("V"); //voltimetro



if(STEon==0)delay_ms(2);
if(STEon==0)out2++; //verifica botao ste
if(out2==1)STE=1;
if(out2==2)STE=0, out2=0;

write_eeprom(gravar_ste,STE); //gravar STE na eeprom

lcd_gotoxy(1,1); //instrução LCD sistema trio
if(STE==1)lcd_putc("STE:on");
else lcd_putc("STE:off");



if(TELAon==0)delay_ms(2);
if(TELAon==0)out1++; //verifica botao tela
if(out2==1)TELA=1;
if(out2==2)TELA=0, out1=0;

write_eeprom(gravar_tela,TELA); //gravar TELA na eeprom

lcd_gotoxy(1,2); //instrução LCD tela
if(TELA==1)lcd_putc("TELA:on");
else lcd_putc("TELA:off");



if(valor<=168)BZ=1;
else BZ=0;


valor=0, tensão=0; //converssão voltimetro, zerando variaveis
goto loop;
}

linguagem simples, pois estou começando agora com programação.

então o que eu queria é algo do tipo assim:

pino1=1, pino2=0, delay 20us

pino1=0, pino2=1, delay 20us

Link para o comentário
Compartilhar em outros sites

ola, amigo... tenta o seguinte

/*Inserted into .c file before main():*/

#int_TIMER2

void TIMER2_isr(void)

{

pino1= ~pino1;

pino2= ~pino2;

}

/*Inserted into .c file in main():*/

setup_timer_2(T2_DIV_BY_4,4,1); //20.0 us overflow, 20.0 us interrupt

enable_interrupts(INT_TIMER2);

enable_interrupts(GLOBAL);

Outra coisa, Ivan...

você não está tendo problemas na hora da compilação desse seu código?... você criou os seguintes defines:

#define gravar_tela 10// o numero é o local de memoria

#define gravar_ste 11

e declarou variáveis com o mesmo nome

int gravar_tela;//variaveis para gravação

int gravar_ste;

*não olhei o seu código inteiro, portanto não analisei a sua lógica e nem a sintaxe do seu programa...

Link para o comentário
Compartilhar em outros sites

Então o codigo fico muito grande e tive que muda de PIC, contudo depois de todas as alterações tentei compilar e esta dando erro assim:"Unknown Keyword in # fuses".

Ja tentei um monte de coisa e não estou achando o erro. Codigo completo abaixo:


#use delay(clock=20000000)

#FUSES NOWDT // No Watch Dog Timer
#FUSES HS // High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES PUT // Power Up Timer
#FUSES NOPROTECT // Code not protected from reading
#FUSES NODEBUG // No Debug mode for ICD
#FUSES BROWNOUT // Reset when brownout detected
#FUSES NOLVP // No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD // No EE protection
#FUSES NOWRT // Program memory not write protected
#FUSES XT
#FUSES MCLR

#byte RA=0x05
#byte RB=0x06
#byte RC=0x07
#byte RD=0x08
#byte RE=0x09

#include "c:\Flex_lcd.c"

#device adc=10 // Conversor AD operando em modo 10 bits
#define gravar_tela 5 // o numero é o local de memoria
#define gravar_ste 6
#define gravar_wifi 7
#define gravar_MC1 8
#define gravar_MC2 9
#define gravar_MC3 10
#define gravar_MC4 11

//entradas
#bit STEon = ra.3
#bit TELAon = rc.1
#bit VT = ra.4 //detector de presença
#bit WH = rc.0 //Wifi-Hold

#bit MCtx1 = rc.2 //entrada remotas
#bit MCtx2 = rc.3
#bit MCtx3 = rd.0
#bit MCtx4 = rd.1

#bit MCfx1 = ra.5 //entradas fixas
#bit MCfx2 = re.0
#bit MCfx3 = re.1
#bit MCfx4 = re.2

#bit RMT = rb.3 // entrada remoto do player

//saidas
#bit TELA=rd.7
#bit STE=rd.5
#bit Hold=rd.4
#bit buzzer=rd.6
#bit f1=rd.3
#bit f2=rd.2

#bit MC1=rc.7
#bit MC2=rc.6
#bit MC3=rc.5
#bit MC4=rc.4


int out1; //tela
int out2; //ste
int hd; //Hold
int wifi;
int s1;
int s2;
int s3;
int s4;

int gravar_tela; //variaveis para gravação
int gravar_ste;
int gravar_wifi;
int gravar_MC1;
int gravar_MC2;
int gravar_MC3;
int gravar_MC4;

long int tensão; //adc
long int valor;
unsigned long int mil;
unsigned long int mil1;
unsigned long int cem;
unsigned long int dez;

/**************************************************************/
/* Rotina Buzzer */
/**************************************************************/

void beep (int dur,freq)
{
int i;
for(i=0;i<dur;i++)
{
output_high(buzzer);
delay_ms (freq);

output_low(buzzer);
delay_ms (freq);
}}


void beep_curto (void)
{
beep(50,1);
}

void beep_longo (void)
{
beep(100,1);
}

void beep_tec (void)
{
beep(4,1);
}

/**************************************************************/
/* Interrupção por TIMER 2 */
/**************************************************************/

#int_TIMER2
void TIMER2_isr(void)
{
f1= ~f1;
f2= ~f2;
}

/**************************************************************/
/* Inicio do Programa Principal */
/**************************************************************/

main()

{
valor=0, tensão=0, mil=0, mil1=0, cem=0, dez=0;//variaveis do ADC

f1=1,f2=0;//variaveis da fonte externa

out1=0, out2=0, hd=0;//variaveis do programa

buzzer=0, TELA=0, STE=0, Hold=0;//saidas
MC1=0, MC2=0, MC3=0, MC4=0;

set_tris_a(0b00011100);
set_tris_b(0b00001000);
set_tris_c(0b00001111);
set_tris_d(0b00000011);
set_tris_e(0b00000111);

ligado:

if(RMT==0)goto ligado;//verificando se player esta ligado

/**************************************************************/
/* Configurando da Memoria EEPROM */
/**************************************************************/

write_configuration_memory(gravar_tela,TELA);
write_configuration_memory(gravar_ste,STE);
write_configuration_memory(gravar_wifi,wifi);
write_configuration_memory(gravar_MC1,MC1);
write_configuration_memory(gravar_MC2,MC2);
write_configuration_memory(gravar_MC3,MC3);
write_configuration_memory(gravar_MC4,MC4);


lcd_init(); //inicializando LCD
lcd_putc("Ahhhhhh Negão!!!");
lcd_gotoxy(1,2);
lcd_putc(" Controlador HE1");

delay_ms(2000);

/**************************************************************/
/* Leitura da Memoria EEPROM */
/**************************************************************/

TELA= read_EEPROM (gravar_tela);
STE= read_EEPROM (gravar_ste);
wifi= read_EEPROM (gravar_wifi);
MC1= read_EEPROM (gravar_MC1);
MC2= read_EEPROM (gravar_MC2);
MC3= read_EEPROM (gravar_MC3);
MC4= read_EEPROM (gravar_MC4);


inicio:

/**************************************************************/
/* Configurando Interrupção por TIMER 2 */
/**************************************************************/

setup_timer_2(T2_DIV_BY_4,4,1); //20.0 us overflow, 20.0 us interrupt
enable_interrupts(INT_TIMER2);
enable_interrupts(GLOBAL);

/**************************************************************/
/* Leitura e Apresentação do ADC e Tensão */
/**************************************************************/

setup_adc_ports(RA2_ANALOG); //configurando adc
setup_adc(ADC_CLOCK_INTERNAL);
set_adc_channel(2);
delay_us (10);

valor = read_adc(); //lendo valor de leitura

//read_adc(ADC_START_ONLY);
//valor=read_adc(ADC_READ_ONLY);

tensão= (valor*0,014648)*1000; //calculos da tensão

if(tensão==14999)tensão=15000;

mil=tensão/10000; //colocar resultados inteiro
mil1=tensão-(mil*10000);
cem=(tensão-(mil*10000)-(mil1*1000))/100;
dez=(tensão-(mil*10000)-(mil1*1000)-(cem*100))/10;

/*mil("%d")=tensão/10000;//colocar resultados inteiro
mil1("%d")=tensão-(mil*10000);
cem("%d")=(tensão-(mil*10000)-(mil1*1000))/100;
dez("%d")=(tensão-(mil*10000)-(mil1*1000)-(cem*100))/10;*/

lcd_gotoxy(10,2);

lcd_putc(0x30+mil);
lcd_putc(0x30+mil1);
lcd_putc(".");
lcd_putc(0x30+cem);
lcd_putc(0x30+dez);
lcd_putc("V");

/**************************************************************/
/* Habilitação da Proteção por Tensão */
/**************************************************************/

if(valor<=737)
{
beep_curto(), delay_ms(1000);
beep_curto(), delay_ms(1000);
goto inicio;
}

/**************************************************************/
/* Leitura e Identificação do botão Hold */
/**************************************************************/

if(WH==0)delay_ms(2000);
if(WH==0)hd=hd++,beep_tec();

if(hd==1) Hold=1, goto pulo;
if(hd>=2) Hold=0, hd=0;

/**************************************************************/
/* Leitura e Identificação do botão Wifi */
/**************************************************************/

if(WH==0)delay_ms(2);
if(WH==0)wifi==wifi++,beep_tec();

if(wifi>=2)wifi=0;

write_eeprom(gravar_wifi,wifi); //gravar wifi

if(wifi==1) goto presenca;
else goto botao;

/**************************************************************/
/* Detecção do Sensor de Presença e Comandos Remoto */
/**************************************************************/

presenca:

if(VT==1)goto remoto; //identificando presença
else beep_longo(), goto inicio;


remoto:

if(MCtx1==0)delay_ms(2);
if(MCtx1==0)s1=s1++;
if(MCtx2==0)delay_ms(2);
if(MCtx2==0)s2=s2++;
if(MCtx3==0)delay_ms(2);
if(MCtx3==0)s3=s3++;
if(MCtx4==0)delay_ms(2);
if(MCtx4==0)s4=s4++;

/**************************************************************/
/* Leitura e Identificação dos botões */
/**************************************************************/

botao:

if(STEon==0)delay_ms(2);
if(STEon==0)out2=out2++, beep_tec(); //verifica botao ste
if(out2==1)STE=1;
if(out2>=2)STE=0, out2=0;
write_eeprom(gravar_ste,STE); //gravar STE na eeprom


if(TELAon==0)delay_ms(2);
if(TELAon==0)out1=out1++, beep_tec(); //verifica botao tela
if(out1==1)TELA=1;
if(out1>=2)TELA=0, out1=0;
write_eeprom(gravar_tela,TELA); //gravar TELA na eeprom


if(MCfx1==0)delay_ms(2); //lendo entrada dos botões
if(MCfx1==0)s1=s1++,beep_tec();

if(MCfx2==0)delay_ms(2);
if(MCfx2==0)s2=s2++,beep_tec();

if(MCfx3==0)delay_ms(2);
if(MCfx3==0)s3=s3++,beep_tec();

if(MCfx4==0)delay_ms(2);
if(MCfx4==0)s4=s4++,beep_tec();

/**************************************************************/
/* Identificação Valor das Variaveis */
/**************************************************************/

pulo:

if(s1==1)MC1=1;
if(s1>=2)s1=0, MC1=0;
write_eeprom(gravar_MC1,MC1);

if(s2==1)MC2=1;
if(s2>=2)s2=0, MC2=0;
write_eeprom(gravar_MC2,MC2);

if(s3==1)MC3=1;
if(s3>=2)s3=0, MC3=0;
write_eeprom(gravar_MC3,MC3);

if(s4==1)MC4=1;
if(s4>=2)s4=0, MC4=0;
write_eeprom(gravar_MC4,MC4);

/**************************************************************/
/* Apresentação de Resultados no LCD */
/**************************************************************/

lcd_gotoxy(1,1); //instrução LCD sistema trio
if(STE==1)lcd_putc("STE:on");
else lcd_putc("STE:off");

lcd_gotoxy(1,2); //instrução LCD tela
if(TELA==1)lcd_putc("TELA:on");
else lcd_putc("TELA:off");

lcd_gotoxy(9,1); //instrução LCD wifi
if(wifi==1)lcd_putc("WIFI:on");
else lcd_putc("WIFI:off");


goto inicio;
}
#include <16F877A.H>

Quando eu tiro o #fuses mclr muda o erro, ai aparece: " expecting an identifier"

Link para o comentário
Compartilhar em outros sites

Sinceramente, eu toh achando meio estranho essa sua forma de programar, tenho a sensação que está misturando algumas coisas... no momento eu não posso conferir ela pra você.. mas vou tentando de ajudar em alguns pontos específicos... ok...


//faça aqui as configurações dos #fuses

#include <16f877a.h>

#device adc=10

#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O

#use delay(clock=4000000)

//insira aqui todos os seus arquivos de inclusão (#include "****.h")
#include "main.h" //abrir um arquivo onde você coloca todas os seus defines, variaveis, etc...

#include "Flex_lcd.c"

//suas funções//
/************************************************** ************/
/* Rotina Buzzer */
/************************************************** ************/

void beep (int dur,freq)
{
int i;
for(i=0;i<dur;i++)
{
output_high(buzzer);
delay_ms (freq);

output_low(buzzer);
delay_ms (freq);
}}


void beep_curto (void)
{
beep(50,1);
}

void beep_longo (void)
{
beep(100,1);
}

void beep_tec (void)
{
beep(4,1);
}

/************************************************** ************/
/* Interrupção por TIMER 2 */
/************************************************** ************/

#int_TIMER2
void TIMER2_isr(void)
{
f1= ~f1;
f2= ~f2;
}


//main
void main()
{

valor=0, tensão=0, mil=0, mil1=0, cem=0, dez=0;//variaveis do ADC

f1=1,f2=0;//variaveis da fonte externa

out1=0, out2=0, hd=0;//variaveis do programa

buzzer=0, TELA=0, STE=0, Hold=0;//saidas
MC1=0, MC2=0, MC3=0, MC4=0;

set_tris_a(0b00011100);
set_tris_b(0b00001000);
set_tris_c(0b00001111);
set_tris_d(0b00000011);
set_tris_e(0b00000111);

/************************************************** ************/
/* Configurando Interrupção por TIMER 2 */
/************************************************** ************/

setup_timer_2(T2_DIV_BY_4,4,1); //20.0 us overflow, 20.0 us interrupt
enable_interrupts(INT_TIMER2);
enable_interrupts(GLOBAL);

/************************************************** ************/
/* Configuração do ADC e Tensão */
/************************************************** ************/

setup_adc_ports(RA2_ANALOG); //configurando adc
setup_adc(ADC_CLOCK_INTERNAL);

while(true)
{
//seu código aqui
}

}


agora o arquivo main.h onde você deve colocar os defines e variáveis globais...


//arquivo main.h//


#byte RA=0x05
#byte RB=0x06
#byte RC=0x07
#byte RD=0x08
#byte RE=0x09


#define gravar_tela 5 // o numero é o local de memoria
#define gravar_ste 6
#define gravar_wifi 7
#define gravar_MC1 8
#define gravar_MC2 9
#define gravar_MC3 10
#define gravar_MC4 11

//entradas
#bit STEon = ra.3
#bit TELAon = rc.1
#bit VT = ra.4 //detector de presença
#bit WH = rc.0 //Wifi-Hold

#bit MCtx1 = rc.2 //entrada remotas
#bit MCtx2 = rc.3
#bit MCtx3 = rd.0
#bit MCtx4 = rd.1

#bit MCfx1 = ra.5 //entradas fixas
#bit MCfx2 = re.0
#bit MCfx3 = re.1
#bit MCfx4 = re.2

#bit RMT = rb.3 // entrada remoto do player

//saidas
#bit TELA=rd.7
#bit STE=rd.5
#bit Hold=rd.4
#bit buzzer=rd.6
#bit f1=rd.3
#bit f2=rd.2

#bit MC1=rc.7
#bit MC2=rc.6
#bit MC3=rc.5
#bit MC4=rc.4


int out1; //tela
int out2; //ste
int hd; //Hold
int wifi;
int s1;
int s2;
int s3;
int s4;

int gravar_tela; //variaveis para gravação
int gravar_ste;
int gravar_wifi;
int gravar_MC1;
int gravar_MC2;
int gravar_MC3;
int gravar_MC4;

long int tensão; //adc
long int valor;
unsigned long int mil;
unsigned long int mil1;
unsigned long int cem;
unsigned long int dez;

Na minha opinião não é muito bacana e nem muito usual em C o uso de label e goto, o ideal seria você substituir tudo isso por funções... Pelo que eu vi o problema do seu #fuses é que você declarou #fuses HS (crystal oscilador) e #fuses xt(crystal ressonador, se eu não me engano) e o uC só pode usar um ou outro...

Estou a disposição... falou

Link para o comentário
Compartilhar em outros sites

Usar GOTO e o LABEL tem que ter alguma experiencia.

Eles otimizam muito o código pois cada rotina(ou função) usa a pilha do PIC por isso é mais lento,ja com GOTO o programa salto imediatamento para onde começa o LABEL,mas se não tiver prática,o programa pode travar pois não estará usando a PILHA do PIC e terá de saber exatamente onde o programa salta e o que fazer.

Link para o comentário
Compartilhar em outros sites

Mas nos fuses mesmo usando uma linha que sempre usei em programação esta dando erro:

#fuses nowdt, nobrownout, nolvp, put, xt, noprotect, mclr

e no label e goto estou usando um modo que aprendi no tecnico e ate então sempre funcionou. vocês acham que esta errada a forma de escrita?

Link para o comentário
Compartilhar em outros sites

vtrx,

quando o programa da um salto usando o GOTO para um label ele gasta 2 ciclos de máquinas e como você disse ele não usa a pilha do PIC, ao contrário de chamadas usando o CALL e as interrupções que salvam o contexto numa stack para só então ir para uma rotina...

Quando a gente estuda linguagem C, aprendemos que uso do goto não é uma técnica muito "elegante", mas se pesquisarmos um pouco veremos que se bem utilizado se torna algo muito útil... eu mesmo já me deparei com situações em que necessitei usar desta técnica... melhor usar o goto do que fazer chamadas recursivas (algo improvável para uC)... enfim, essa é uma discussão que vai longe...

esse site fala coisas interessantes sobre o uso do goto

http://sergioprado.org/voce-usa-goto-nos-seus-codigos-em-c/

Link para o comentário
Compartilhar em outros sites

Não estou gerando controvérsia,é que é melhor ,quando se está propgramando para microcontroladores,pensarmos sempre no resultado para o micro,pois microcontroladores são infinitamente inferiorres se comparado a microprocessadores com vários giga ou vários núcleos.

A linguagem C para microcontroladores é uma adaptação,sempre temos que pensar no microcontrolador primeiro,ao contrário de se programar em C para windows,Linux etc,onde devemos seguir a risca a sintese da linguagem C pois estaremos programando sobe controle de um sistema operacional.

Link para o comentário
Compartilhar em outros sites

Você tem razão vtrx, quando se está programando em um ambiente inferior deve-se pensar no hardware de como ele se comporta, etc... você não gerando controvérsias, é importante essas discussões podem desmistificar muitas opiniões formadas, não é verdade...

o que é importante saber é que tudo vira assembly por exemplo se abrirmos o código gerado pelo compilador (arquivo *.lst) visualizaremos o techo seguinte.

.................... while(!tout_overflow){}

0082: BTFSS 33.0

0083: GOTO 082

ou seja, ao invés de usar um goto para loops de repetição, use o que a linguagem C te disponibiliza, o código vai ficar muito mais limpo, irá obedecer as boas da programação, etc...

Voltando ao assunto desse tópico, e aí Ivan como está o seu projeto? você alterou os #fuses?

Link para o comentário
Compartilhar em outros sites

sim alterei os fuses ai coomeçou a aparecer erros dimais no programa.

tentei compilar um programa que tenho q funciona e também deu erro, acho que meu compilador esta com problema.

Entretanto hoje e amanha estarei revendo meu programa para tentar tirar esses goto e também fazer download de uma versão nova do ccs

Link para o comentário
Compartilhar em outros sites

Desculpe a demora meu computador esta com problemas estou tendo que entrar por uma lan house enquanto ele não volta.

Então ja tentei fazer esse sistema que você esta mencionando, mas não achei a forma correta de instalação do programa e nem ele free.

Qto ao programa estou tentando fazer algumas modificações aindam assim que possivel posto de novo

grato

Link para o comentário
Compartilhar em outros sites

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

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...

 

GRÁTIS: ebook Redes Wi-Fi – 2ª Edição

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!