Re: Kycklingkvitter från uC?
Postat: 25 mars 2010, 23:14:20
Kul att ni gillart'! =)
Jag har labbat med en gammal PIC16F627 med intern 4MHz-oscillator. PORTB.3 (PWM-utgången) är kopplad till en piezohögtalare (traditionella högtalare går nog också bra) via ett 220 ohms motstånd.
Koden borde funka på alla PIC som har TMR0, TMR2 och PWM-modul. Ifall INTRC är på 8 MHz behöver man ställa in prescaler 2 på TMR0.
Med mindre ändringar borde koden även funka på PICar med bara en TMR0. Då får man använda två utgångar, med varsitt motstånd kopplad till högtalaren.
Koden är skriven för CC5X, men borde gå att använda med andra kompilatorer utan några större ändringar. Kompilerad med CC5X tar den 184 word programminne och 37 bytes variabelminne.
Jag har labbat med en gammal PIC16F627 med intern 4MHz-oscillator. PORTB.3 (PWM-utgången) är kopplad till en piezohögtalare (traditionella högtalare går nog också bra) via ett 220 ohms motstånd.
Koden borde funka på alla PIC som har TMR0, TMR2 och PWM-modul. Ifall INTRC är på 8 MHz behöver man ställa in prescaler 2 på TMR0.
Med mindre ändringar borde koden även funka på PICar med bara en TMR0. Då får man använda två utgångar, med varsitt motstånd kopplad till högtalaren.
Koden är skriven för CC5X, men borde gå att använda med andra kompilatorer utan några större ändringar. Kompilerad med CC5X tar den 184 word programminne och 37 bytes variabelminne.
Kod: Markera allt
#include <INT16CXX.H>
#pragma config |= 0xFF7F
#pragma config PWRTE=on, WDTE=off, FOSC=0b100, BODEN=on
#pragma bit speaker @ PORTB.3
#pragma bit TRISspeaker @ TRISB.3
//----- Globals -------------------------------------------------------
bit active;
uns8 halfPeriod;
uns16 periodCounter;
uns8 volume;
uns8 step;
uns8 stepPeriod;
uns8 stepCounter;
struct
{
uns8 volume;
uns8 startHalfPeriod;
uns16 periodCount;
uns8 step;
uns8 stepPeriod;
} ramps[4], *rampPointer, *rampEndPointer;
//----- Interrupts ----------------------------------------------------
#pragma origin 4
interrupt int_server(void)
{
int_save_registers // W, STATUS (and PCLATH)
char sv_FSR = FSR; // save FSR
if (T0IF)
{
T0IF = 0;
TMR0-=halfPeriod-3;
if (active)
{
if (volume<4)
CCP1CON |= volume<<4;
else
CCPR1L = 1;
active=0;
}
else
{
CCP1CON&=0b11001111;
CCPR1L=0;
active=1;
}
if (--stepCounter==0)
{
halfPeriod+=step;
stepCounter=stepPeriod;
}
if (--periodCounter==0)
{
rampPointer++;
if (rampPointer>=rampEndPointer)
{
rampPointer=&ramps[0];
}
volume=rampPointer->volume;
step=rampPointer->step;
halfPeriod=rampPointer->startHalfPeriod;
stepCounter=stepPeriod=rampPointer->stepPeriod;
periodCounter=rampPointer->periodCount;
}
}
FSR = sv_FSR; // restore FSR
int_restore_registers // W, STATUS (and PCLATH)
}
void init();
//----- Main ----------------------------------------------------------
void main()
{
volume=0;
rampEndPointer=&ramps[sizeof(ramps)/sizeof(ramps[0])];
rampPointer=rampEndPointer;
ramps[0].volume=1;
ramps[0].startHalfPeriod=110;
ramps[0].periodCount=100;
ramps[0].step=-1;
ramps[0].stepPeriod=10;
ramps[1].volume=2;
ramps[1].startHalfPeriod=100;
ramps[1].periodCount=500;
ramps[1].step=0;
ramps[1].stepPeriod=255;
ramps[2].volume=4;
ramps[2].startHalfPeriod=100;
ramps[2].periodCount=500;
ramps[2].step=1;
ramps[2].stepPeriod=8;
//Pausen mellan pipen
ramps[3].volume=0;
ramps[3].startHalfPeriod=100;
ramps[3].periodCount=5000;
ramps[3].step=0;
ramps[3].stepPeriod=255;
init();
while(1)
{
nop();
}
}
void init()
{
OPTION_REG = 0b1.0001.000; //Pullups, no TMR0 prescaler
CMCON = 0x07; //Turn off comparator
TRISB = 0;
PORTB = 0;
PR2 = 1-1;//1 MHz
T2CON = 0b00000100; //T2ON;
CCPR1L = 0; //0% duty
CCP1CON = 0b00001111; //PWM active high
T0IE=1; //TMR0 interrupt enabled
GIE=1; //Global interrupt enabled
}