Ir ao conteúdo

Programar PIC em C


CIS

Posts recomendados

Postado

amigo shunt, não consegui compilar o codigo citado.sera que servira no PIC12F675?? ja que esse pic não tera PORTX, e sim GPIO, e a mesma coisa??

você ja compilou esse codigo?

valeu a sugestão...

Postado
você ja compilou esse codigo?

Não foi testado! foi mesmo para elucidar uma ideia de como fazer, mas com pequenas mudanças pode ser funcional sim.

Mande o código que já está pronto ou as sequencias que deseja assim fica mais simples implementar.

Abç.

Postado

Mande o código que já está pronto ou as sequencias que deseja assim fica mais simples implementar.

como estou usando o PIC12F675, com apenas cinco saidas, eu queria colocar essas saidas em tres sequencias diferentes, ate ai, entendido, certo?

então eu queria fazer assim: ligar GP0, delay 0,5 segundo, desligar.

ligar GP1, delay 0,5 segundo, desligar.

ligar GP2, delay 0,5 segundo, desligar.

ligar GP4, delay 0,5 segundo, desligar.

ligar GP4, delay 0,5 segundo, desligar.

essa é a 1ª sequencia...quero repeti-la por 5 vezes.

depois ligar todos ao mesmo tempo, aguardar 0,5 segundo e desligar, repeti-la tambem por cinco vezes...

e se eu conseguir de uma pra outra, acho que fica fácil colocar outras sequencias.... valeu shunt!!!! me ajuda mais ai cara!!!! novato e triste né!!!kkkk

/*Programa para tentar colocar 03 sequencias no PIC12F675*/

int x=0;

void main() {

CMCON = 7; //desabilita o comparador.

ANSEL = 0; //desabilita o conversor A/D.Temos agora todos os pinos digitais.

TRISIO = 0; //faz todos os pinos saidas, com exceção do GP3.

GPIO = 0; //todos os pinos inicialmente desligados.

while(1) { //enquanto houver alimentação.

for(x=0;x<=10;x=x+1)

{

gpio.F0 = 1;

delay_ms(500);

gpio.F0 = 0;

delay_ms(500);

gpio.F1 = 1;

delay_ms(500);

gpio.F1 = 0;

delay_ms(500);

gpio.F2 = 1;

delay_ms(500);

gpio.F2 = 0;

delay_ms(500);

gpio.F4 = 1;

delay_ms(500);

gpio.F4 = 0;

delay_ms(500);

gpio.F5 = 1;

delay_ms(500);

gpio.F5 = 0;

delay_ms(500);

}

for(x=0;x<=10;x=x+1)

{

gpio.F0 = 1;

gpio.F1 = 1;

gpio.F2 = 1;

gpio.F4 = 1;

gpio.F5 = 1;

delay_ms(200);

gpio.F0 = 0;

gpio.F1 = 0;

gpio.F2 = 0;

gpio.F4 = 0;

gpio.F5 = 0;

delay_ms(200);

}

for(x=0;x<=10;x=x+1)

{

gpio.F0 = 1;

delay_ms(500);

gpio.F0 = 0;

delay_ms(500);

gpio.F1 = 1;

delay_ms(500);

gpio.F1 = 0;

delay_ms(500);

gpio.F2 = 1;

delay_ms(500);

gpio.F2 = 0;

delay_ms(500);

gpio.F4 = 1;

delay_ms(500);

gpio.F4 = 0;

delay_ms(500);

gpio.F5 = 1;

delay_ms(500);

gpio.F5 = 0;

delay_ms(500);

gpio.F4 = 1;

delay_ms(500);

gpio.F4 = 0;

delay_ms(500);

gpio.F2 = 1;

delay_ms(500);

gpio.F2 = 0;

delay_ms(500);

gpio.F1 = 1;

delay_ms(500);

gpio.F1 = 0;

delay_ms(500);

gpio.F0 = 1;

delay_ms(500);

gpio.F0 = 0;

delay_ms(500);

}

}

}

espero opiniões sobre esse codigo, ainda não testei , na verdade nem tentei compilar ainda, mas gostaria de opiniões a respeito da logica e se acham que ira funcionar...

Postado

CIS, compile o código abaixo e faça um teste. Ele deve atender as duas primeiras sequencias.



void main() {
CMCON = 7; //desabilita o comparador.
ANSEL = 0; //desabilita o conversor A/D.Temos agora todos os pinos digitais.
TRISIO = 0; //faz todos os pinos saidas, com exceção do GP3.
GPIO = 0; //todos os pinos inicialmente desligados.

while(1) { //enquanto houver alimentação.

for(y = 0; y <= 4; y++){ // repete 5 vezes o laço abaixo:
for(x = 0; x <= 6; x++){
if(x == 3) x += 1;
GPIO = 1<<x;
Delay_ms(500);
}
GPIO = 0; // desliga o GPIO.
}

Delay_ms(500);
GPIO = 63; // ativa todas as saídas.

for(x = 0; x <= 10; x++){
GPIO = ~GPIO; // inverte todas as saídas.
Delay_ms(200);
}

GPIO = 0;

}
}
unsigned short x = 0, y = 0;

Abç.

Postado
CIS, compile o código abaixo e faça um teste. Ele deve atender as duas primeiras sequencias.



void main() {
CMCON = 7; //desabilita o comparador.
ANSEL = 0; //desabilita o conversor A/D.Temos agora todos os pinos digitais.
TRISIO = 0; //faz todos os pinos saidas, com exceção do GP3.
GPIO = 0; //todos os pinos inicialmente desligados.

while(1) { //enquanto houver alimentação.

for(y = 0; y <= 4; y++){ // repete 5 vezes o laço abaixo:
for(x = 0; x <= 6; x++){
if(x == 3) x += 1;
GPIO = 1<<x;
Delay_ms(500);
}
GPIO = 0; // desliga o GPIO.
}

Delay_ms(500);
GPIO = 63; // ativa todas as saídas.

for(x = 0; x <= 10; x++){
GPIO = ~GPIO; // inverte todas as saídas.
Delay_ms(200);
}

GPIO = 0;

}
}
unsigned short x = 0, y = 0;

Abç.

valeu Shunt!!! o programa começou travar mas deu pra ter uma noção... agora so não entendi porque declarar duas variaveis ( " x " , " y " são variaveis certo??) quando a parte de inverter o estado do GPIO, o GP2 ficou inverso aos demais, não entendi mas consegui mudar um pouco essa parte e deu certo... podemos comentar o programa ??? tipo o porque foi feito determinadas coisas, pra que eu possa entender melhor um pouco.. rsrsr!!!!

valeu cara

abs

Postado
agora so não entendi porque declarar duas variaveis ( " x " , " y ")

Esse bloco (botão abaixo) é executado 7 vezes (o correto seria 6, corrigido abaixo) controlado pela Var "x":


if(x == 3) x += 1;
GPIO = 1<<x;
Delay_ms(500);
}
for(x = 0; x <= 5; x++){   

Já o "y" é responsável por executar o bloco "x" (acima) 5x (você disse que necessitava que cada pedaço fosse executado 5x).

O pedaço de código abaixo, analisa se a Var "x" está na posição do GP3.

Se estiver, ele adiciona 1 na Var "x" e pula para GP4.

if(x == 3) x += 1;

o GP2 ficou inverso aos demais, não entendi

Normal :D, fiz o código de cabeça, poderia dar alguma falha! Imagina que tive uma prova de Banco de Dados e o prof mandou efetuar as consultas no papel :wacko: ... rsrs deu o mesmo tilt.

podemos comentar o programa ?

Ele já tem alguns comentários nos blocos principais, diga exatamente o que não entendeu.

Desculpe os micos, compilar na massa encefálica não é uma boa ideia!

Abç.

Postado

valeu mesmo, ontem mesmo eu estive analisando os blocos e e ja tinha tirado essa conclusão de que uma var era pra sequencia de pinos e a outra pra contagem das repetições, ai eu mudei uns numeros e comprovei tanto as mudanças nas velocidades quanto no numero de repetições, ja to conseguindo "brincar um pouquinho"!!! você tem algum material que fala das interrupçoes em especial... como fazer um delay de 2 horas?? tentei com 7200000 ms, mas não funcionou...rsrsrs... "acho que ja quero complicar um pouco mais meus estudos"!!!!!!!!kkkkkkkkkkkk

valeu!!!toda ajuda é bem vinda quando se estuda sozinho...

abraços!!!

valeu!!! tudo certo ate aqui.... eu ja tinha mais ou menos essa ideia, so pra que pra um novato, tudo tem que ficar bem claro, sabe como éh!!!!

mas agora uma outra coisa, como fazer um pino funcionar por 5 segundos e ficar desligado por 2 horas??? tentei um delay de 7200000 milisegundos, mas sem sucesso...

obrigado pela ajuda, ta sendo de grande valia!!!!

abraços!!!!

Postado
tentei um delay de 7200000 milisegundos

Ainda bem que o compilador não fala senão teria lhe xingado :D

Vejo que agora é hora de começar o estudo dos timers.

E fazer seu proprio delay.

O bom disso é que voce pode fazer outras coisas no PIC e deixar o timer contando.

Aqui no forum tem várias formas de gerar bases de tempo de 1 segundo com o Timer 1 ou 0 gerando essa fica fácil fazer uma de 5horas.

Abs.

Postado
Ainda bem que o compilador não fala senão teria lhe xingado :D

Vejo que agora é hora de começar o estudo dos timers.

E fazer seu proprio delay.

O bom disso é que voce pode fazer outras coisas no PIC e deixar o timer contando.

Aqui no forum tem várias formas de gerar bases de tempo de 1 segundo com o Timer 1 ou 0 gerando essa fica fácil fazer uma de 5horas.

Abs.

kkkkkkkkkkkkkk:confused:

valeu Felipe!!! mas pode me dar uma dica por onde começar??

obrigado por me avisar sobre o compilador:huh:

to começando com o PIC12F675, mas esse pequeno de oito pinos parece ser mai complicado do que alguns maiores...

Postado

mais duvidas, voltando ao assembly...

pessoal, agora e sobre o timer 0, e a respeito dos registradores relativos a ele... eu uso o OPTION pra ler ou escrever?? e como saber qual INTCON escolher, se o do banco 0 ou do banco 1?? lembro que to com o PIC12F675, que tem apenas dois bancos...

Postado

pessoal... estou usando o PIC12F675, e iniciando o timer0, mas estou com essa duvida:

usando o oscilador interno do pic, que é de 4MHz, pra eu achar a frequencia interna de trabalho desse PIC, tenho ainda que dividir 4MHz por 4, ou 4MHz ja é a freuqencia de trabalho interno do pic???

se alguem tiver de algum material do timer 0, postem pra mim por favor....

Postado

Sempre em qualquer oscilador, para encontrar o tempo do ciclo de máquina do PIC você deve dividir o clock por 4, apenas para ciclo de máquina, para trabalho com timers via hardware (como o timer 0) você deve usar a frequencia sem dividir por 4.

Abs.

Postado
para trabalho com timers via hardware (como o timer 0) você deve usar a frequencia sem dividir por 4.

Felipe, nesse caso (sem divisão por 4) é apenas quando o timer é incrementado via RA4 (operando em modo contador, mas também pode ser dividido utilizado o prescaler interno), estou certo? Fiquei na duvida agora!

Veja a figura abaixo:

fig3-51.gif

Sempre consulto o material gratuito no site da mikroe. Referências:

http://www.mikroe.com/eng/products/view/285/book-pic-microcontrollers-programming-in-c/

Abç.

Postado

esse timer 0 esta sendo um problema...kkkkk

mais de uma semana ja se foi

estou com dificuldade nas formulas... veja se estou certo;

frequencia interna do pic = frequencia oscilador / 4.

tempo pra estourar = frequencia interna / prescaler * 256

mas a inicialização do PIC12F675 , como fazer... sera que alguem tem um exemplo pra esse modelo??? exemplo de como configurar o mocrocontrolador...

Postado
... alguem tem um exemplo pra esse modelo? exemplo de como configurar o microcontrolador...

Coloque um led + resistor de 270~470R no pino GP0.

Compile o código abaixo (foi testado com o proteus e funciona corretamente):


volatile unsigned short x = 0;


void interrupt()
{
// Timer0 Interrupção: Frequencia = 18.00 Hz /// Periodo = 0.055552 segundos.
if (INTCON.TMR0IF ==1) // checa se a flag é do timer0 (pois pode ser outras se mais interrupções estiverem habilitadas).
{
x++;
if(x == 18){
led = !led;
x = 0;
}

}
INTCON.TMR0IF = 0; // limpa a flag
INTCON.TMR0IE = 1; // reabilita a interrupção
TMR0 = 39; // preload do timer0

}

void main() {
CMCON = 7;
ANSEL = 0;
TRISIO = 0x08;
GPIO = 0x00;
led = 0;
//Veja no datasheet como ficam as configurações abaixo:
OPTION_REG.T0CS = 0;
OPTION_REG.T0SE = 0;
OPTION_REG.PSA = 0;
OPTION_REG.PS2 = 1;
OPTION_REG.PS1 = 1;
OPTION_REG.PS0 = 1;
TMR0 = 39; // preload do timer0

INTCON = 0;
INTCON.TMR0IE = 1;
INTCON.TMR0IF = 0;
INTCON.GIE = 1;

for(;;){}

}
volatile sbit led at GPIO.B0;

O MateusLPS e o Felipe_Electronic poderão ajudar com os calculos!

Eles explicam muito bem, tenho certeza (creio que já fizeram isso no fórum, procurei e não tive resultados).

O exemplo acima possui uma variavel "x" que é incrementada a cada interrupção. Quando ela atingir o valor 18 (todos os calculos foram feitos para que o timer estoure 18 vezes por segundo, mas pode ser conforme sua necessidade, observando alguns parametros), temos aproximadamente 1 segundo. Então o led muda de estado e "x" recebe 0. Isso irá se repetir enquanto houver alimentação.

Foi feito na correria, espero que sirva de apoio.

Abç.

Postado
Coloque um led + resistor de 270~470R no pino GP0.

Compile o código abaixo (foi testado com o proteus e funciona corretamente):


volatile unsigned short x = 0;


void interrupt()
{
// Timer0 Interrupção: Frequencia = 18.00 Hz /// Periodo = 0.055552 segundos.
if (INTCON.TMR0IF ==1) // checa se a flag é do timer0 (pois pode ser outras se mais interrupções estiverem habilitadas).
{
x++;
if(x == 18){
led = !led;
x = 0;
}

}
INTCON.TMR0IF = 0; // limpa a flag
INTCON.TMR0IE = 1; // reabilita a interrupção
TMR0 = 39; // preload do timer0

}

void main() {
CMCON = 7;
ANSEL = 0;
TRISIO = 0x08;
GPIO = 0x00;
led = 0;
//Veja no datasheet como ficam as configurações abaixo:
OPTION_REG.T0CS = 0;
OPTION_REG.T0SE = 0;
OPTION_REG.PSA = 0;
OPTION_REG.PS2 = 1;
OPTION_REG.PS1 = 1;
OPTION_REG.PS0 = 1;
TMR0 = 39; // preload do timer0

INTCON = 0;
INTCON.TMR0IE = 1;
INTCON.TMR0IF = 0;
INTCON.GIE = 1;

for(;;){}

}
volatile sbit led at GPIO.B0;

O MateusLPS e o Felipe_Electronic poderão ajudar com os calculos!

Eles explicam muito bem, tenho certeza (creio que já fizeram isso no fórum, procurei e não tive resultados).

O exemplo acima possui uma variavel "x" que é incrementada a cada interrupção. Quando ela atingir o valor 18 (todos os calculos foram feitos para que o timer estoure 18 vezes por segundo, mas pode ser conforme sua necessidade, observando alguns parametros), temos aproximadamente 1 segundo. Então o led muda de estado e "x" recebe 0. Isso irá se repetir enquanto houver alimentação.

Foi feito na correria, espero que sirva de apoio.

Abç.

deu pra ter uma noção SHUNT, mas na hora de compilar não passou

to usando o mickroC for PIC... deu erro na primeira linha

volatile sbit led at gpio.b0;

e uma nova duvida, de onde é o termo volatile???

ainda não tinha visto???

obrigado pela dica...

Postado

é assim ó, O timer0 funciona da seguinte forma:



Tempo de incremento no TMR0 = 4/FOSC (sem prescaler)

Se usarmos o prescaler o tempo de um incremento no
registrador tIMER0 sera:

Tempo de incremento no TMR0 = 4 * Prescaler / FOSC



tendeu?

Abs.

Postado
é assim ó, O timer0 funciona da seguinte forma:



Tempo de incremento no TMR0 = 4/FOSC (sem prescaler)

Se usarmos o prescaler o tempo de um incremento no
registrador tIMER0 sera:

Tempo de incremento no TMR0 = 4 * Prescaler / FOSC



tendeu?

Abs.

beleza, essa parte ok... mas to apanhando na inicialização do timer desse pic

12F675... agora tenho uma base com o exemplo do shunt, mas o codigo não compilou... os calculos eu ate encontro e consigo fazer, mas na hora de configurar o hardware é que estou com dificuldades...

obrigado, vou anotar essas formulas aqui....vamos a um exemplo

meu PIC trabalha com o oscilador iterno de 4MHz, então:

tempo de incremento = 4/4 ,

mas devo uasr a freq.oscilador em hz ou em mhz para fazer a conta??

e o tempo sera dado em segundos ou us???

Postado
deu pra ter uma noção SHUNT, mas na hora de compilar não passou to usando o mickroC for PIC... deu erro na primeira linha

volatile sbit led at gpio.b0;

Sugiro que baixe a nova versão 5.2 Pro. É gratuita até 2K, e tem um algoritmo de otimização até 40% maior que a versão que você usa.

Tente o código abaixo:


#define led GPIO.F0
//Se o define acima der erro, comente-o e descomente abaixo:
//#define led GPIO.B0

volatile unsigned short x = 0;

void interrupt()
{
// Timer0 Interrupção: Frequencia = 18.00 Hz /// Periodo = 0.055552 segundos.
if (INTCON.TMR0IF ==1) // checa se a flag é do timer0 (pois pode ser outras se mais interrupções estiverem habilitadas).
{
x++;
if(x == 18){
led = !led;
x = 0;
}

}
INTCON.TMR0IF = 0; // limpa a flag
INTCON.TMR0IE = 1; // reabilita a interrupção
TMR0 = 39; // preload do timer0
}

void main() {
CMCON = 7;
ANSEL = 0;
TRISIO = 0x08;
GPIO = 0x00;
led = 0;

//Veja no datasheet como ficam as configurações abaixo:
OPTION_REG.T0CS = 0;
OPTION_REG.T0SE = 0;
OPTION_REG.PSA = 0;
OPTION_REG.PS2 = 1;
OPTION_REG.PS1 = 1;
OPTION_REG.PS0 = 1;
TMR0 = 39; // preload do timer0

INTCON = 0;
INTCON.TMR0IE = 1;
INTCON.TMR0IF = 0;
INTCON.GIE = 1;

for(;;){}

}

Esqueci de mencionar que neste código o oscilador interno é configurado para 4Mhz.

Download do Arquivo .HEX <<< compilado com a versão Pro 5.2

e uma nova duvida, de onde é o termo volatile???

ainda não tinha visto

Ok, agora você vai baixar o manual do compilador e procurar a diretiva volatile, assim vai entender por qual motivo ela foi usada! Caso não entenda, explico brevemente.

Abç.

Postado
valeu Shunt, vou correr atras agora!!!!

de volta!!!!

Shunt, seu codigo funcionou , contando que com um espaço de tempo ele vai perdendo sincronismo com o relogio de parede...não da um tempo exato de um segundo... mas me clareou bem a ideia... mas vamos as novas duvidas, sera que eu posso escrever o numero binario no registro option direto, pra não ter que trabalhar com todos os bits, ou em C não da??

e ainda, como aumentar a contagem, porque fiz uns calculos aqui, montei o codigo e compilou ate, gravei no micro mas não executou nada... vou ver se consigo posta-lo mas tarde pra ver as opnioes de vocês...

valeu pessoal!!!!

absss...

Postado
Shunt, seu codigo funcionou , contando que com um espaço de tempo ele vai perdendo sincronismo com o relogio de parede...não da um tempo exato de um segundo...

Natural! o oscilador interno é um arranjo RC, não é preciso mesmo.

Se for necessário precisão nos tempos, sacrifique 2 pinos e coloque um cristal externo + trimmer para ajuste de clock.

sera que eu posso escrever o numero binario no registro option direto, pra não ter que trabalhar com todos os bits, ou em C não da??

Sim, pode. Eu prefiro da forma que foi passada, pois é mais fácil assimilar a ideia de como o foi configurado.

OPTION_REG = 0b........; // substitua os pontos pela sua configuração binária ou mesmo em hexadecimal, decimal etc.

e ainda, como aumentar a contagem, porque fiz uns calculos aqui, montei o codigo e compilou ate, gravei no micro mas não executou nada

Código?

Abç.

Postado
é assim ó, O timer0 funciona da seguinte forma:


Tempo de incremento no TMR0 = 4/FOSC (sem prescaler)

Se usarmos o prescaler o tempo de um incremento no

registrador tIMER0 sera:

Tempo de incremento no TMR0 = 4 * Prescaler / FOSC

esse tempo de incremento sera dado em segundos, milisegundos ou microsegundos????

ex: para um prescaler 1:8 no timer zero, o tempo de incremento sera 0,5 ... mas qual sera a unidade de medida???? e esse tempo de incremento é a mesma coisa que estouro????

#define led GPIO.F0

//Se o define acima der erro, comente-o e descomente abaixo:

//#define led GPIO.B0

volatile unsigned short contador = 0;

void interrupt()

{

if (INTCON.TMR0IF ==1) // checa se a flag é do timer0 (pois pode ser outras se mais interrupções estiverem habilitadas).

{

contador++;

if(contador == 500){

led = !led;

x = 0;

}

}

INTCON.TMR0IF = 0; // limpa a flag

INTCON.TMR0IE = 1; // reabilita a interrupção

TMR0 = 0; // preload do timer0

}

void main() {

CMCON = 7;

ANSEL = 0;

TRISIO = 0x08;

GPIO = 0x00;

led = 0;

//Veja no datasheet como ficam as configurações abaixo:

OPTION_REG.T0CS = 0;

OPTION_REG.T0SE = 0;

OPTION_REG.PSA = 0;

OPTION_REG.PS2 = 0;

OPTION_REG.PS1 = 1;

OPTION_REG.PS0 = 0;

TMR0 = 0; // preload do timer0

INTCON = 0;

INTCON.TMR0IE = 1;

INTCON.TMR0IF = 0;

INTCON.GIE = 1;

for(;;){}

}

porque este codigo não fuciona????

Postado

Vamos analisar:

volatile unsigned short contador = 0;

Acima você declarou como unsigned short, portanto a contagem máxima é 255

Já no trecho abaixo, você espera que "contador" chegue a 500, mas "ela" pode contar até 255. :confused:

if (INTCON.TMR0IF ==1){
contador++;
if(contador == 500){
led = !led;
x = 0;
}

Ainda no código acima você "zera" a variavel "x", que por sua vez não foi declarada.

Corrigindo:


volatile unsigned int contador;

void interrupt(){
if (INTCON.TMR0IF ==1){
contador++;
if(contador == 500){
led = !led;
contador = 0;
}
INTCON.TMR0IF = 0; // limpa a flag
INTCON.TMR0IE = 1; // reabilita a interrupção
TMR0 = 39; // preload do timer0
}

Tente aí, abraço!

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