Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

How to generate 38 KHZ wave

Status
Not open for further replies.

shico90

New Member
Hello,
I want to generate a 38 KHZ wave using the MCU, Howa can i do that?
and how can I change the duty cycle?
Thank you
 
Is exact 38.0kHz afford or is nearly 38kHz OK ?

A ATMEGA Microcontroller can generate a adjustible frequency with fixed 50% duty cycle or a fixed frequency, that appends from the Controller clock, with adjustible duty cycle.
The key ist the Hardware Timer 1.

To generate both it must be done by software.
A possible way to do this, is to use the Comparematch Interrupts of Timer1.
Comp B is adjusted to the period time of 38 kHz, Comp A is the equivalent of Duty cycle.

Example:
Clock Frequency 16MHz Prescaler 1
Comp B is adjusted to 444, Comp A is adjusted to 148.
Timer1 ( TCNT1 ) starts at 0, PWM OUT is switched on.
When arrived 148 Timer 1 Comp A Routine switch of PWM Out.
When Arrived 444 Timer 1 Comp B resets TCNT1 Register and switch the PWM OUT on.
So you get an PWM Signal with nearly 36kHz an 33,3% Duty Cycle.
The Frequency is adjutable with Comp B the Duty Cycle is adjustible with Comp A.

One thing is clear. The Microcontroller is a slave of frequency generating and could not do many other things. The routines must be as short as possible, best in Assembler.

An other possible way is to take a Controller frequency that generate with prescaler automaticly 38kHz and use a PWM Generator. I think Fast PWM will be the best mode for this project - Be Careful about not possible Duty Cycles in this Mode!
So the PWM Generating will be done complete in Hardware.
The Controller Core is free for other applications.
0 and 100% Duty Cycle are not possible. A little Pulse will occour all time. You can avoid this by Software.
 
Thank you for your reply
So you are saying that the first way works but it will make the MCU busy and can't do other things
but aren't we adjust the timers in the start of the program and then leave it to work alone?
I mean that doesn't need us to interfere every time in the program, Am I right?
 
So you are saying that the first way works but it will make the MCU busy and can't do other things
but aren't we adjust the timers in the start of the program and then leave it to work alone?
In first example the Frequency / PWM Generation is fully made by software in both Timer 1 Comparematch Interrupts.
Between two Cycles are only 444 Clock Cycles that give you ~ 440 Assembler commands for 1 Cycle.

A further Interrupt will make trouble and disturb the PWM generation.
Normal programs in Main Routine will work, but they are very often interupted by the Comparematch. So it'll not run with full speed.

The other way is too calculate the Controller Frequency or an external Frequency for Timer 1 that there will be an 38kHz Signal generated.
E.g. 38Khz * 256 = 9.728kHz in Fast PWM Mode 8Bit, of Timer 1 with Prescaler 1.
So the PWM generation runs into Hardware. The Controller core has nothing to do beside load the Comparematch A ( B ) Register with duty cycle information.
This PWM has 256 steps between 0% an 100% duty cycle.
Additional there is no needing of Interupts for PWM generation in this mode.

By using a 10MHz Crystal, is not exact 38kHz reachable!

In fast PWM Mode one Duty cycle is not Possible.
Im not shure ist that 0% or 100% ?

Look into Datasheet to clear that.
 
Code:
Chip type           : ATmega16
Program type        : Application
Clock frequency     : 9,728000 MHz
Memory model        : Small
External SRAM size  : 0
Data Stack size     : 256
*****************************************************/

#include <mega16.h>

// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
#asm ("nop");
// Place your code here

}

// Declare your global variables here

void main(void)
{
// Declare your local variables here

// Input/Output Ports initialization
// Port A initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
PORTA=0x00;
DDRA=0x00;

// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=Out Func2=In Func1=In Func0=In 
// State7=T State6=T State5=T State4=T State3=0 State2=T State1=T State0=T 
PORTB=0x00;
DDRB=0x08;

// Port C initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
PORTC=0x00;
DDRC=0x00;

// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
PORTD=0x00;
DDRD=0x00;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 9728,000 kHz
// Mode: Fast PWM top=FFh
// OC0 output: Non-Inverted PWM
TCCR0=0x69;
TCNT0=0x00;
OCR0=0x80;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// INT2: Off
MCUCR=0x00;
MCUCSR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x01;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;

// Pulsewidth
OCR0=80;
// Global enable interrupts
#asm("sei")

while (1)
      {
      #asm ("nop");
      // Place your code here

      };
}
This Code generates a 38kHz Square Wave with adjustible duty cycle when using a 9.728MHz crystal.
It runs in Timer 0.
Duty Cycle is adjustable by manipulation of OCR0 register.
Possible Values are 0 to 255.

OCR0 = 0 generates a Pulse of 0.1µs
0% Duty Cycle is'nt possible!
100% Duty Cycle is possible!

The problem will be, to get such an crystal.

This Program is only tested in simulator, not in an real Controller.

It's written in "C" on CodeVision AVR Compiler.
 
Last edited:
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top