Follow along with the video below to see how to install our site as a web app on your home screen.
Note: This feature may not be available in some browsers.
Krumlink said:I tried to create a 38kHZ square wave with a PIC18F1330, but it did not work. I was wondering if anybody had any code or etc on how to generate one. I will post my code later.
Krumlink said:Yes, I wanted to generate a continous square wave at 38kHZ for IR detection in a upcoming robot
Krumlink said:What would be the frequency of the interrupts? I think it would be easier just to use the PWM software to easily generate the 38kHZ wave, then I could just upload the new software with an ICSP if I wanted to include interrupts
/*
* PWM registers configuration
* Fosc = 8000000 Hz
* Fpwm = 37735.85 Hz (Requested : 38000 Hz)
* Duty Cycle = 50 %
* Resolution is 7 bits
* Prescaler is 1
* Ensure that your PWM pin is configured as digital output
* see more details on http://www.micro-examples.com/
* this source code is provided 'as is',
* use it at your own risks
*/
PR2 = 0b00110100 ;
T2CON = 0b00000100 ;
CCPR1L = 0b00011010 ;
CCP1CON = 0b00011100 ;
//This project is for producing a 38kHZ wave for a infrared detecting robot
#pragma config WDT = OFF
#pragma config OSC = INTIO2
#pragma config PWRT = ON
#pragma config LVP = OFF
#include <p18f1330.h>
void main(void)
{
// speed up the clock to 8MHz
OSCCONbits.IRCF0=1; OSCCONbits.IRCF1=1;
OSCCONbits.IRCF1=1;
OSCCONbits.IRCF2=1;
OSCCONbits.SCS0=0;
OSCCONbits.SCS1=0;
//18F1330 Speed clock up to 32MHz using PLL
OSCTUNEbits.PLLEN=1;
ADCON1 = 0; // make RA0 digital
TRISA = 0xFE;
while(1)
{
PORTA = 0xFF;
delay_us(13);
PORTA = 0x00;
delay_us(13);
}
}
#include <system.h>
//Target PIC16F628A configuration word
#pragma DATA _CONFIG, _CP_OFF & _LVP_OFF & _BODEN_OFF & _MCLRE_ON & _PWRTE_ON & _WDT_OFF & _INTOSC_OSC_NOCLKOUT
//Set clock frequency
#pragma CLOCK_FREQ 4000000
// Period = CCP1Period * PreScaler * clock
// 3.2 ms = 200 * 16 *1
// Duty Cycle
// Period * Duty% / 4 * Osc
// 3.2 * .5 = 1.6
// 1600 / 4 = 400
// 3.2 ms
/*
#define CCP1Period 199
#define CCP1DutyCy 399
*/
// 1.6 ms
/*
#define CCP1Period 99
#define CCP1DutyCy 199
*/
// 1.25 ms = 800 hz
/*
#define CCP1Period 77
#define CCP1DutyCy 155
*/
// Set Prescaler to 1:1
// 32 khz
/*
#define CCP1Period 30
#define CCP1DutyCy 63
*/
// 38 khz
#define CCP1Period 25
#define CCP1DutyCy 51
/*
// 40 khz
#define CCP1Period 24
#define CCP1DutyCy 49
*/
bit running = 0;
unsigned char turnon[6] = { 0x40, 4, 1, 0, 0xbc, 0xbd};
void interrupt( void )
{
// Handle timer1 interrupt
// Used to time the length of pulses
if( pir1.TMR1IF )
{
running = 0;
t1con.TMR1ON = 0; // Turn TIMER1 off
pir1.TMR1IF = 0; //clear timer 1 interrupt bit
}
}
void xmit_pulse(short micro_pulse)
{
static short clock_count;
clock_count = 65536 - micro_pulse;
LOBYTE( tmr1l, clock_count);
HIBYTE( tmr1h, clock_count);
pir1.TMR1IF = 0; // Reset overflow bit
t1con.TMR1ON = 1; // Turn TIMER1 on
running = 1;
trisb.3 = 0;
t2con.TMR2ON = 1;
while (running) ; // Wait for pulse time to end
t2con.TMR2ON = 0;
tmr2 = 0;
portb.3 = 0;
trisb.3 = 1;
}
void send_on(void) {
static char i;
static char j;
static char t;
static unsigned char *ovalue;
static unsigned char k;
// Send it 3 times
for (k = 0; k < 3; k++) {
ovalue = &turnon;
xmit_pulse(3550); // 4 ms header
delay_100us(10); // 1 ms
delay_10us(6); // .6 ms
for (i = 0; i < 6; i++) {
for (j = 8; j > 0; j--) {
t = j - 1;
if (test_bit(*ovalue, t)) {
// A one
xmit_pulse(512); // 400 micro s
delay_100us(10); // 1 ms
delay_10us(2); // .2 ms
}
else {
// A zero
xmit_pulse(512); // 400 micro s
delay_100us(3); // 400 micro s
}
}
ovalue++;
}
// End bit
xmit_pulse(400);
delay_ms(70);
}
}
void main( void )
{
static unsigned char Low;
static unsigned char High;
static unsigned int Duty = CCP1DutyCy;
ccp1con = 0; // CCP Module off
tmr2 = 0; // Clear Timer 2
//Configure port B
trisb = 0x00;
trisb.3 = 1;
option_reg.NOT_RBPU = 0;
//Initialize port B
portb = 0;
cmcon = 7; //disable comparators
//Set timer 1
//prescaler rate 1:1
//Internal clock (FOSC/4)
t1con = 00001000b;
// Configure Capture/Compare/PWM for PWM
// at 38khz.
//Set timer 2 prescaler rate
// T2CPS = 1:1
t2con = 01001000b;
//t2con = 0;
pr2 = CCP1Period;
Low = Duty & 3;
High = Duty >> 2;
ccpr1l = High;
ccp1con = 00001100b;
ccp1con.5 = Low.1;
ccp1con.4 = Low.0;
intcon.PEIE = 1; // Enable peripheral interrupts
intcon.GIE = 1; // Enable global interrupt
pie1.TMR1IE = 1; // Enable Timer 1 interrupts
// Main Loop
send_on();
while (1) {
}
}
trisb.3 = 0;
t2con.TMR2ON = 1; // Turn 38khz on
while (running) ; // Wait for pulse time to end
t2con.TMR2ON = 0; // Turn 38khz off
tmr2 = 0;
void xmit_pulse(short micro_pulse)
{
static short clock_count;
clock_count = 65536 - micro_pulse;
LOBYTE( tmr1l, clock_count);
HIBYTE( tmr1h, clock_count);
pir1.TMR1IF = 0; // Reset overflow bit
t1con.TMR1ON = 1; // Turn TIMER1 on
running = 1;
while (running) {
asm {
bsf _irout,1
nop // 1
nop // 2
nop // 3
nop // 4
nop // 5
nop // 6
nop // 7
nop // 8
nop // 9
nop // 10
nop // 11
nop // 12
bcf _irout,1
nop // 1
nop // 2
nop // 3
nop // 4
nop // 5
nop // 6
nop // 7
nop // 8
}
}
irout = 0;
}
// 38 khz
#define CCP1Period 12
#define CCP1DutyCy 25
In the main init routine
// Configure Capture/Compare/PWM for PWM
// at 38khz.
//Set timer 2 prescaler rate
// T2CPS = 1:4
t2con = 00000001b;
pr2 = CCP1Period;
Low = Duty & 3;
High = Duty >> 2;
ccpr1l = High;
ccp1con = 00001100b;
ccp1con.5 = Low.1;
ccp1con.4 = Low.0;
And to turn it on permanent like for a test
// test
trisb.3 = 0;
t2con.TMR2ON = 1;
while (1) ;
August Treubig said:To do true PWM, you let the hardware do it.