0
\$\begingroup\$

I need to generate 5 kHz square wave pulse with varying duty cycle on PORTA.0.

The AVR micro here is an ATMEGA16 running with a 12 MHz external crystal. Some part of the following code is generated by code wizard in codevision.

The TIMER0 is set for 1 μs. I’ve set the timer for 1μs and tmax=8 which must produce an 8 μs pulse period with 50% duty cycle. But Proteus simulation shows near 200 μs pulse period. Is this because of improper coding or because of some problem in Proteus simulation? The proteus schematic for the code is here.

enter image description here

#include <mega16.h>

// Declare your global variables here
#define offA0 PORTA.0=0
#define onA0  PORTA.0=1
unsigned int t = 0; //t increments up to count each timer overflow 
unsigned int tmax = 8; //max num of interrupts to complete one modulated pulse period. Therefore the 
// pulse period would become tmax*(timer period)
unsigned int percent = 50;// the duty cycle of the wave

//dutycycle function checks the num of interrupts which 
//represents the elapsed time so far. then, it toggles the PORTA.x 
// based on the duty cycle
void dutycycle(unsigned int j)
{
    unsigned int jmax = percent*tmax/100;
    if (j<jmax)
    {
        onA0;
    }        
    else
    {
        offA0;
    }
    if (t>=tmax)
    {
        t = 0;
    }
} 

// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
// Reinitialize Timer 0 value
TCNT0=0xF4;
// Place your code here
PORTA.0 = !PORTA.0;
t = t + 1;
}

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

// Input/Output Ports initialization
// Port A initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In 
DDRA=(0<<DDA7) | (0<<DDA6) | (0<<DDA5) | (0<<DDA4) | (0<<DDA3) | (0<<DDA2) | (0<<DDA1) | (1<<DDA0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T 
PORTA=(0<<PORTA7) | (0<<PORTA6) | (0<<PORTA5) | (0<<PORTA4) | (0<<PORTA3) | (0<<PORTA2) | (0<<PORTA1) | (0<<PORTA0);

// Port B initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In 
DDRB=(0<<DDB7) | (0<<DDB6) | (0<<DDB5) | (0<<DDB4) | (0<<DDB3) | (0<<DDB2) | (0<<DDB1) | (0<<DDB0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T 
PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0);

// Port C initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In 
DDRC=(0<<DDC7) | (0<<DDC6) | (0<<DDC5) | (0<<DDC4) | (0<<DDC3) | (0<<DDC2) | (0<<DDC1) | (0<<DDC0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T 
PORTC=(0<<PORTC7) | (0<<PORTC6) | (0<<PORTC5) | (0<<PORTC4) | (0<<PORTC3) | (0<<PORTC2) | (0<<PORTC1) | (0<<PORTC0);

// Port D initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In 
DDRD=(0<<DDD7) | (0<<DDD6) | (0<<DDD5) | (0<<DDD4) | (0<<DDD3) | (0<<DDD2) | (0<<DDD1) | (0<<DDD0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T 
PORTD=(0<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (0<<PORTD0);

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 12000.000 kHz
// Mode: Normal top=0xFF
// OC0 output: Disconnected
// Timer Period: 1 us
TCCR0=(0<<WGM00) | (0<<COM01) | (0<<COM00) | (0<<WGM01) | (0<<CS02) | (0<<CS01) | (1<<CS00);
TCNT0=0xF4;
OCR0=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=(0<<OCIE2) | (0<<TOIE2) | (0<<TICIE1) | (0<<OCIE1A) | (0<<OCIE1B) | (0<<TOIE1) | (0<<OCIE0) | (1<<TOIE0);

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// INT2: Off
MCUCR=(0<<ISC11) | (0<<ISC10) | (0<<ISC01) | (0<<ISC00);
MCUCSR=(0<<ISC2);

// Global enable interrupts
#asm("sei")

while (1)
      {
      // Place your code here
      dutycycle(t);

      }
}
\$\endgroup\$
1
  • 2
    \$\begingroup\$ Tips: 'kHz' (small 'z'). 'uS' is micro-siemens. You're looking for 'µs', micro-seconds. (Use HTML entity &mu; for µ.) Your code isn't indented correctly so that's making it hard to read and debug - for you and for us. \$\endgroup\$
    – Transistor
    Mar 16 '20 at 19:47
2
\$\begingroup\$

Use the timer in PWM mode. It runs completely in hardware, just set period and duty. No need to manually toggle anything. The pin most likely is not pin 0 of port A.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.