How to generate the frequency from 9hz to 12 hz with the step size of 0.1hz

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 

How to generate the frequency from 9hz to 12 hz with the step size of 0.1hz

1,303 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by angiey on Tue Mar 15 05:06:21 MST 2016
Hello Everyone!!

I'm using LPC1114 development board, so as of now getting 1hz frequency,
Below is the part of the code:
By varying the prescaler register, i'm getting different frequency by increasing
the prescaler with step size of 50[i.e., 12000,12050,12100 etc].

But how to continuously get the frequency from 9 hz to 11hz with a step of 1hz with some time delay??
Kindly guide me how to proceed.

#include "LPC11xx.h"          
#include "system_LPC11xx.h"

int main()
{
SystemInit();
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<16) |(1<<6) | (1<<8) ;
LPC_IOCON ->PIO1_9 |= (1 << 0);             //PIN1_9 = CT16B1_MAT0
LPC_TMR16B1 ->MR0 = 2000;                   //50% Duty Cycle
LPC_TMR16B1 ->PR = 12000;
LPC_TMR16B1 ->MR3 = 4000;                   //Cycle Length
LPC_TMR16B1 ->MCR |= (1 << 10);            //TC Reset on MR3 Match
LPC_TMR16B1 ->PWMC |= (1 << 0);           //PWM Mode
LPC_TMR16B1 ->TCR |= (1 << 0);              //GO
}


Thanks,
Angiey.
标签 (1)
0 项奖励
回复
4 回复数

1,205 次查看
lpcware
NXP Employee
NXP Employee
bump
0 项奖励
回复

1,205 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by angiey on Wed Apr 06 00:54:46 MST 2016
Thanks for the suggestion.

But I have doubt on what basis the values are assigned to MR3 and should values to be assigned to this below equation??

uint32_t tmrCalcMR = ((float)periphClock) / (freq*tmrCalcPR) + 0.5; // TmrCalcPR = 1, freq is how I calculate the 1/2 period count

Since i'm using MR0 and MR3 registers.

As per the below code calculation for the frequency for 3hz i'm getting is:
OUTPUT FREQ= CRYSTAL FREQ / (MR3*PR);
So for 3hz 48Mhz / (4000*4000) = 3Hz.

By keeping PR value constant how to rewrite the above equation in match registers.

Kindly go through the below code:

#include<stdio.h>
#include "LPC11xx.H" 
#include "glcd_api.h"

#defineINCR(char)1
#defineHOLD(char)0
#defineDECR(char)-1

char line_buf[21];
volatile  int   seconds_indicator;
unsigned char DONE_str[] = "DONE";
//static    char  seconds_str[] = "* *";
unsigned char TIME_str[] = "TIME_SEL";

unsigned int temp_hours_selected=0;
unsigned int temp_minutes_selected=02;
unsigned int hours_selected=0;
unsigned int minutes_selected=02; 

volatile signed char hours_remaining;
volatile signed char minutes_remaining;
volatile signed char seconds_remaining = 59;
signed int timer_flag;

unsigned int wait_for_any_key_counter_0;
unsigned int wait_for_any_key_counter_1;
unsigned char restart_therapy;

unsigned long spill_over_count; 
 
unsigned int timer1_overflow_count = 0;
unsigned int timer0_overflow_count = 0;
unsigned char spill_over_count_loaded;
unsigned char spill_over_count1_loaded;
unsigned char show_time_flag;
unsigned char show_seconds_flag;
unsigned char therapy_is_over;

unsigned int b,j;
int current_frequencyx10;
unsigned long cycle_time_microsec;

struct THERAPY
{
unsigned int match3;
unsigned int match0;
signed char  inc_hold_dec;
unsigned int prescal;
};

signed int inc_hold_dec;

char ma3[10];
char ma0[10];
char pr[10];
char a[20];

struct THERAPY recover[]=
{
4000,4000,2000, //3hz

2000,1000,2500, //9.6hz//mr3,mr0,pr

1390,695 ,2500,  //14.1hz
};

int phase_num;
unsigned int mat3;
unsigned int mat0;
unsigned int pre;
void delay(void);
void tostring(char [],int);

void TIMER32_0_IRQHandler(void)         //ISR ROUTINE//interrupt3
      {
  if(therapy_is_over == 0)
{
if(spill_over_count1_loaded == 1)
  {
spill_over_count1_loaded = 0;
timer1_overflow_count = 0;
if(LPC_TMR32B0->IR & 0x01)
         {
     LPC_TMR32B0->IR=1;    //clear interrupt flag //

if((seconds_remaining == 0) && (minutes_remaining == 0) && (hours_remaining == 0))
    {
          hours_remaining = 0;
minutes_remaining = 0;
seconds_remaining=0;
 therapy_is_over = 1;
 init_xy_axis(PAGE0 + 4 , COL0 + 34);  
   lcd_display_string((unsigned char*)line_buf);
 sprintf(line_buf, "%s", DONE_str); 
    } 
 
else if(seconds_remaining ==-1)
       {
seconds_remaining = 59;
   minutes_remaining--;
     }
else if(minutes_remaining ==-1)
   {
minutes_remaining = 59;
--hours_remaining;
}
else
{
seconds_remaining--;
            }
             show_time_flag = 1;
}
}

else
   {
if((timer1_overflow_count % 10) == 0)
  show_seconds_flag = 1;
timer1_overflow_count++;
if(timer1_overflow_count == 120)   //1230,120
    {
   spill_over_count1_loaded = 1;
            LPC_TMR32B0->TC=0x00;    //here assigned values for * blinking           //0x82 is correct//0x84   //0x88=6sec
LPC_TMR32B0->PR=0x01;    //here assigned values for * blinking 
}
}
} 

}




void Timer32_0_init(void)  //Timer32 bit initialization  and PWM genaration //for timer operation
{
 LPC_SYSCON->SYSAHBCLKCTRL |= (1<<16) | (1<<6) | (1<<9);  //cloc+3
 LPC_IOCON->PIO1_6 |= 0x02; /* Timer0_32 MAT0 */
 LPC_IOCON->PIO1_7 &= ~0x07;
 LPC_IOCON->PIO1_7 |= 0x02; /* Timer0_32 MAT1 */
 LPC_IOCON->PIO0_1 &= ~0x07;
 LPC_IOCON->PIO0_1 |= 0x02; /* Timer0_32 MAT2 */

 LPC_TMR32B0->MR0 = 50 * ((SystemCoreClock/(LPC_TMR32B0->PR+1))/100); //[if we won't use MR0 timer operation stops] /* Generate interrupt each 10 ms */


 LPC_TMR32B0->MCR = 0x03;
 LPC_TMR32B0->TC=0x00;  //0x00;//0x82 is correct//0x84   //0x88=6sec
 LPC_TMR32B0->PR=0x01;  //1
 NVIC_EnableIRQ(TIMER_32_0_IRQn);
  /* initialize timer */
 LPC_TMR32B0->TCR=0;  //0 or 1 is not affected in timer operation or in freq

}



void timer162(void)
{
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<16) | (1<<6) | (1<<8);
LPC_IOCON->PIO1_9 |= (1 << 0); // Pin no 17 = CT16B1_MAT0(checking out put )
LPC_TMR16B1->PWMC |= (1 << 0); // PWM Mode channel zero fro CT16B1.
LPC_TMR16B1->MCR  |= (1<<10) ;// TC reset on MR3 Match
LPC_TMR16B1->MR3  = mat3;  //4000//22900;; // Cycle Length
LPC_TMR16B1->MR0  = mat0;  //11200; // 50% Duty Cycle
LPC_TMR16B1->PR   = pre;
LPC_TMR16B1->TCR  = (1<<0); //TC & PC enabled for counting.

}

//Below is the code for frequency generation///
void StruVariable(void)
{
  mat3=recover[phase_num].match3;
mat0=recover[phase_num].match0;
pre=recover[phase_num].prescal;

init_xy_axis(PAGE0 + 6,COL0 + 34 ); 
sprintf(line_buf," %02d:%02d         ", hours_remaining, minutes_remaining);
lcd_display_string(line_buf);

tostring(ma3,mat3);
init_xy_axis(PAGE0,COL0);
   lcd_display_string((unsigned char*)ma3);//

tostring(ma0,mat0);
init_xy_axis(PAGE0+2 ,COL0);
lcd_display_string((unsigned char*)ma0);//

tostring(pr,pre);
init_xy_axis(PAGE0+4,COL0);
lcd_display_string((unsigned char*)pr);//

cycle_time_microsec = 10000000/current_frequencyx10;

timer162();
   phase_num++;

if(phase_num>=6)
  {
phase_num=0;
  }
else if(phase_num==0)
 {

LPC_TMR32B0->TCR = 0;
 }

}


void delay(void)
   {
  unsigned long i;

  for(i=0;i<1000000;i++);//10000000
mat3=recover[phase_num].match3;
mat0=recover[phase_num].match0;
pre=recover[phase_num].prescal;

   }      



int ma;
int ba;
 
int main(void) 
  {
init_glcd();
glcd_clear();
back_light_on();

timer_flag=0;   //set the flag for timer operation
therapy_is_over = 0;

Timer32_0_init();

show_time_flag = 0;
show_seconds_flag = 0;
seconds_indicator = 0;

while(1)
{
  if(show_seconds_flag == 1)
 {
show_seconds_flag = 0;
   Timer32_0_init();
    }

while(1)
  {
hours_selected = temp_hours_selected;
minutes_selected = temp_minutes_selected;
hours_remaining = hours_selected;
minutes_remaining = minutes_selected;
   
LPC_TMR32B0->TCR = 1;


while(1)  
  {
StruVariable();
delay();

    }
  }

 }
    }



void tostring(char str[],int num)
 {
int i, rem, len = 0, n;

n = num;
while(n != 0)
 {
len++;
n /=10; } 
for(i=0;i<len;i++)
{
rem = num % 10;
num = num / 10;
str[len - (i + 1)] = rem + '0';
}
str[len] = '\0';
 }



Please do comment on the above part of the code.

Regards,
Angiey.
0 项奖励
回复

1,205 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by mathseng on Tue Apr 05 20:02:50 MST 2016
Hi,
I suggest an alternative to your PWM generation.
If you are seeking to just create a square wave of 50% duty cycle, a simpler alternative is to just have the output pin toggling every period, and have a shorter period.

I have posted code which does this for the LPC1347 in "Change PWM pulse length".
This code allows continuous updates of frequency, without causing invalid cycle lengths/glitches.

My code calculates MR on every change - your frequency sweep is only 22 items, so you could make more efficient code using a table.
I also recommend that you use the 32-bit timer with the prescaler set to 0 (PR divisor (TmrCalcPR) == 1).

For frequency parameter passed in as float, my code works fine, but where the frequency parameter is integral, the following line needs updating:
- change line by adding cast for integral frequency - leave unchanged if freq is float.
uint32_t tmrCalcMR = ((float)periphClock) / (freq*tmrCalcPR) + 0.5;       //  TmrCalcPR = 1, freq is how I calculate the 1/2 period count
to
        uint32_t tmrCalcMR = ((float)periphClock) / ((uint64_t)freq*tmrCalcPR) + 0.5;       //  TmrCalcPR = 1, freq is how I calculate the 1/2 period count

mathseng
0 项奖励
回复

1,205 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by IanB on Mon Apr 04 14:21:25 MST 2016
I'm assuming you've already thought about using a look-up table for the MR0 and MR3 values, and that that isn't accurate enough for you.

You get the best accuracy if you use the 32-bit timer and don't use the prescaler and set MR0 and MR3 accordingly, you will get the best accuracy which will get you within 20ns (on a 48MHz clock). 20ns error at 10Hz is within 0.00002%

Your values will be 4800000 and 240000 at 10Hz,  4571428 and 2285714 at 10.1Hz, 4363636 and 2181818 at 11Hz etc.
0 项奖励
回复