galib.tan
Newbie level 6
- Joined
- Jan 5, 2012
- Messages
- 11
- Helped
- 2
- Reputation
- 4
- Reaction score
- 2
- Trophy points
- 1,283
- Activity points
- 1,379
Hi everybody
I'm facing some problems with the following code. I'm using dsPIC 30F2010 and clocking it at 128MHz (overclocking 8MHz crystal and 16x PLL). I'm generating a PWM of 100kHz. I want to make the AD conversion start with the special event trigger from the PWM module. The AD conversion is supposed to start when the PTMR value reaches the peak (up/down PWM mode). I'm checking the ADC interrupt by toggling the RD1 pin. I'm also trying to display the adc value on a 16x2 lcd after every second with timer1. I'm however facing the following problems.
1. The pwm starts as expected after power up but the adc interrupt occurs after a significant delay. This delay varies. If the timer1 interrupt frequency is reduced this delay increases. One more problem is that the RD1 should toggle at 50kHz but it's toggling at 25kHz.
channel1: PWM, channel2: RD1
2. After start up it takes a good length of time (several minutes) to show the ADC value. This delay also varies with the timer1 interrupt frequency (and device clock maybe). After showing for the first time the value refreshes after every second as expected.
Please have a look and help with the problems. Thanks.
I'm facing some problems with the following code. I'm using dsPIC 30F2010 and clocking it at 128MHz (overclocking 8MHz crystal and 16x PLL). I'm generating a PWM of 100kHz. I want to make the AD conversion start with the special event trigger from the PWM module. The AD conversion is supposed to start when the PTMR value reaches the peak (up/down PWM mode). I'm checking the ADC interrupt by toggling the RD1 pin. I'm also trying to display the adc value on a 16x2 lcd after every second with timer1. I'm however facing the following problems.
1. The pwm starts as expected after power up but the adc interrupt occurs after a significant delay. This delay varies. If the timer1 interrupt frequency is reduced this delay increases. One more problem is that the RD1 should toggle at 50kHz but it's toggling at 25kHz.
channel1: PWM, channel2: RD1
2. After start up it takes a good length of time (several minutes) to show the ADC value. This delay also varies with the timer1 interrupt frequency (and device clock maybe). After showing for the first time the value refreshes after every second as expected.
Please have a look and help with the problems. Thanks.
Code:
sbit LCD_RS at LATE5_bit;
sbit LCD_EN at LATD0_bit;
sbit LCD_D4 at LATE1_bit;
sbit LCD_D5 at LATE2_bit;
sbit LCD_D6 at LATE3_bit;
sbit LCD_D7 at LATE4_bit;
sbit LCD_RS_Direction at TRISE5_bit;
sbit LCD_EN_Direction at TRISD0_bit;
sbit LCD_D4_Direction at TRISE1_bit;
sbit LCD_D5_Direction at TRISE2_bit;
sbit LCD_D6_Direction at TRISE3_bit;
sbit LCD_D7_Direction at TRISE4_bit;
void ADC_init(void);
void pwm_init(void);
void timer1_init(void);
void InitTimer1();
volatile unsigned adc_value = 0;
char adc_txt[6];
char txt1[11];
volatile unsigned ticks_lcd;
void main() {
unsigned val = 0;
unsigned long clk=0;
trisd1_bit = 0;
latd1_bit = 0;
InitTimer1();
pwm_init();
ADC_init();
LCD_init();
lcd_cmd(_lcd_cursor_off);
lcd_cmd(_lcd_clear);
ADIF_bit = 0;
INTCON1bits.NSTDIS = 1; // interrupt nesting disabled
PTCONbits.PTEN = 1; // pwm enabled
ADON_bit = 1; // adc enabled
ADCON1bits.ASAM = 1; // auto sampling enabled
ADIE_bit = 1; // adc interrupt enabled
clk = clock_MHz();
longwordtostr(clk, txt1);
lcd_out(2, 1, txt1);
delay_ms(1000);
lcd_cmd(_lcd_clear);
while(1)
{
if(ticks_lcd == 1000)
{
val = adc_value;
wordtostr(val, adc_txt);
lcd_out(2, 4, adc_txt);
ticks_lcd = 0;
}
}
}
void ADC_init(void)
{
ADCON1 = 0x0060; // continue idle mode, integer format, motor control trigger, sequential sampling, SAMP auto = 0
ADCHS = 0x0000; // ch0 positve input AN0, ch0 negative -VREF, CH1 positive AN0, CH1 negative -VREF
ADCSSL = 0; // no scan
ADCON3 = 0x0009; // auto sample time = 0Tad, system clock, ADCS<5:0> = 9
ADCON2 = 0x0104; // converts CH0 and CH1, 2 conversions per interrupt
IPC0 = IPC0 | 0x7000; // priority 7
ADPCFG = 0xFFFE; // AN0 is analog
}
void pwm_init(void)
{
PTCON.PTEN = 0; // pwm timebase off
PWMCON1.PEN1L = 1; // PWM1L pin is configured for pwm operation
PWMCON1bits.PMOD1 = 1; // PWM1L and PWM1H pair is independent
PTCONbits.PTMOD = 2; // free running mode
PTCONbits.PTOPS = 0; // 1:1
PTCONbits.PTCKPS = 0; // 1:1 pwm timebase input clock is Tcy
PTCONbits.PTSIDL = 0; // pwm runs in idle mode
SEVTCMP = 159; // Triggers the ADC in the middle of PWM off time
PTPER = 159; // period register value. 100kHz for up-down mode
PDC1 = 160; // duty cycle 0.5
}
//Timer1
//Prescaler 1:1; PR1 Preload = 32000; Actual Interrupt Time = 1 ms
void InitTimer1(){
T1CON = 0x8000;
TMR1 = 0;
T1IE_bit = 1;
T1IF_bit = 0;
IPC0 = IPC0 | 0x6000; // priority 6
PR1 = 32000; // 1ms
}
void ADCInt() iv IVT_ADDR_ADCINTERRUPT ics ICS_AUTO
{
adc_value = ADCBUF0;
latd1_bit = !latd1_bit;
ADIF_bit = 0;
}
void T1Int() iv IVT_ADDR_T1INTERRUPT ics ICS_AUTO
{
ticks_lcd++;
T1IF_bit = 0;
}