PWM  driver in mc9s12xdp512

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

PWM  driver in mc9s12xdp512

4,404 Views
Lulu
Contributor I
Hello All,
 
I am presently working with the mc9s12xdp512 microcontroller to generator PWM output using inbuild PWM driver.
 
According to my requirement, I need to provide an interface to upper layer to get the present level of pwm output (High or Low) for a particular channel by calling this interface.
 
please let me know whether is it possible to read the present level of the PWM output while in run, since in this controller gives only the details regarding the counter value for duty cycle and period can be controlled and there is no register  giving details about the present level.
 
with best regards,
Lulu
 
Labels (1)
0 Kudos
Reply
14 Replies

1,722 Views
nikosxan
Contributor I
Hello.
 
Is it possible to explain a bit more ?
It isn;t very clear what you mean by 'interface', 'upper layer', , 'present level' etc...
0 Kudos
Reply

1,722 Views
Lulu
Contributor I
Dear nikosxan,
 
I am sorry that my problem was not understandble.
 
While PWM is running ,I want to know the state(High or LOW) of PWm output channel.
 
For e.g-Suppose I am generating a 50% duty cycle on PWM channel 0.
My PWM driver should provide an API(PWM_GetOutputState(uint8 Channel)
 
When I call this API it should return the current status of PWM output channel.
 
I hope,now it is clear prior to my last quetion.
 
Regards,
Satyajit
0 Kudos
Reply

1,722 Views
nikosxan
Contributor I
Ok, got that now....
 
the easiest way to do it is by using a H/W trick... Connect PWM output to another input pin of the MCU (a general I/O pin, configured as an input) and then just read the state of this pin....
This should give you EXACTLY the state (0, 1 ) of the PWM output...
 
I think this is the best think to go, since i don't think there is another way to get the actual state of the PWM pin state...In the MCU there is a stand alone PWM circuit which runs alone with just the initialization (period, duty cycle etc) and it's purpose is to run freely afterwards. I'm not aware of any other internal to the MCU way to 'read' or get the state...
0 Kudos
Reply

1,722 Views
kef
Specialist I
What about reading PTIP register?
0 Kudos
Reply

1,722 Views
Lulu
Contributor I
Dear Kef,
 
Thanks for your reply.It gives  a new dimension to my thinking process.
 
When I initialize PWM,it generates the PWM on a pin.
 
PTIP may give me the state of a particular pin.That means I need to read this register by polling,for this I need some timer.
 
Can it be possible that when the state change occurs on that Pin ,it will notify me by some interrupt.
 
Can you put some light in how we can achive this by PTIP.
 
Regards,
Satyajit 
0 Kudos
Reply

1,722 Views
kef
Specialist I
You don't need any timer for your PWM_GetOutputState() API function. Did requirements change?
Of course you have many ECT timer channels, also some PIT timer channels, RTI, API interrupt. So many possibilities to do periodic sampling.
 
Of course you can have interrupt on port P rising or falling edge. Do you see those KWPx briks on XDT block diagram? KWPs mean key wake up. All KWPs can generate interrupt on pin state change. For port P you should read at least PIEP and PIFP register descriptions.
 
All these little and big secrets are listed in XDT datasheet and CPU12X manual. You would need to ask almost no questions if you read those papers at least once. Regards
0 Kudos
Reply

1,722 Views
Lulu
Contributor I
Hi kef,
 
I tried your method by enabling the interrupt for PWm channel 0.When I put the breakpoint on interrupt,it hit the breakpoint only once.
 
My interrupt enable code is:
 
PIEP_PIEP0 = 1;
PPSP_PPSP0 = 0;
 
the interrupt service routine for key wake up on PWMchannel 0:
 
void PortP_channel0(void)
{
   
    temp_count++;
   
}
 
It is showing 'ILLEGAL_BP'............It is not coming out of ISR.
 
Please suggest whether this concept will work when PWM is enabled or not.
 
Regards,
Satyajit
0 Kudos
Reply

1,722 Views
kef
Specialist I
I don't know what PortP is in your code. Does it expand to something with interrupt keyword?
Your port P ISR should clear port P flags.
0 Kudos
Reply

1,722 Views
Lulu
Contributor I
Hi kef,
 
PortP is just function name.Yes,I have not used the interrupt keyword.
 
In the ISR when I do,
 
void Portp_channel0
{
        PIFP = 0xff;
}
 
this also gives me same reult.It is still not working.Initially, it goes to interrupt once after that it always in one instruction called 'BGND'.\
\
I hope,you can trace the problem
Regards,
Satyajit
0 Kudos
Reply

1,722 Views
kef
Specialist I
S12/S12X interrupt service routine has to exit using RTI instruction. Regular functions exit with RTS or RTC. Check your compiler manual. If you are using Codewarrior, then use interrupt keyword. Also make sure your ISR is put to not paged memory.
0 Kudos
Reply

1,722 Views
Lulu
Contributor I
Hi Kef,
 
I enable PWM channel 0 and PWM Channel1.I  enable the KWP interrupt for PWMchannel 0 and Falling edge.
 
I checked interrupt is commingbut when I watch the PIFP register it is showing values as 3.
 
That means it is seting the bit for PWM channel 1 also.If all PWM channels(7) get enabled so the interrupt will come to one interrupt service routine.
 
In ISR,I need to detect the source of interrupt and call the associated callback function of that channel.
 
e.g-In ISR,suppose I find out the interrupt is by PWM channel0 then Ishould call a call back function of that channel lets...void dumy(void);
 
My interrupt service routine looks like this-
 
interrupt void Pwm_EdgeNotification(void)
{
    /* Determine the interrupt source and call corresponding Notification */
    switch(PIFP)
    {  
        case PWM_0:
   
            if(s_pPwm_Config_Ptr->ChannelConfig                               \
                [PWM_CHANNEL0].PWM_NOTIFICATION_Channel != NULL)               
            {
                 s_pPwm_Config_Ptr->ChannelConfig                             \
                [PWM_CHANNEL0].PWM_NOTIFICATION_Channel();
            }
            else
            {
                /*Do Nothing */
            }
            
            PIFP_PIFP0 = 1;            
           
            break;
        case PWM_1:
   
            if(s_pPwm_Config_Ptr->ChannelConfig                               \
                [PWM_CHANNEL1].PWM_NOTIFICATION_Channel != NULL)               
            {
                 s_pPwm_Config_Ptr->ChannelConfig                             \
                [PWM_CHANNEL1].PWM_NOTIFICATION_Channel();
            }
            else
            {
                /*Do Nothing */
            }
            
            PIFP_PIFP1 = 1;            
           
            break;   
        case PWM_2: 
   
            if(s_pPwm_Config_Ptr->ChannelConfig                               \
                [PWM_CHANNEL2].PWM_NOTIFICATION_Channel != NULL)               
            {
                 s_pPwm_Config_Ptr->ChannelConfig                             \
                [PWM_CHANNEL2].PWM_NOTIFICATION_Channel();
            }
            else
            {
                /*Do Nothing */
            }
            
            PIFP_PIFP2 = 1;            
           
            break;        
        case PWM_3:
   
            if(s_pPwm_Config_Ptr->ChannelConfig                               \
                [PWM_CHANNEL3].PWM_NOTIFICATION_Channel != NULL)               
            {
                 s_pPwm_Config_Ptr->ChannelConfig                             \
                [PWM_CHANNEL3].PWM_NOTIFICATION_Channel();
            }
            else
            {
                /*Do Nothing */
            }
            
            PIFP_PIFP3 = 1;            
           
            break;    
   
        case PWM_4:
  
            if(s_pPwm_Config_Ptr->ChannelConfig                               \
                [PWM_CHANNEL4].PWM_NOTIFICATION_Channel != NULL)               
            {
                 s_pPwm_Config_Ptr->ChannelConfig                             \
                [PWM_CHANNEL4].PWM_NOTIFICATION_Channel();
            }
            else
            {
                /*Do Nothing */
            }
            
            PIFP_PIFP4 = 1;            
           
            break;   
           
        case PWM_5:
          
            if(s_pPwm_Config_Ptr->ChannelConfig                               \
                [PWM_CHANNEL5].PWM_NOTIFICATION_Channel != NULL)               
            {
                 s_pPwm_Config_Ptr->ChannelConfig                             \
                [PWM_CHANNEL5].PWM_NOTIFICATION_Channel();
            }
            else
            {
                /*Do Nothing */
            }
            
            PIFP_PIFP5 = 1;            
           
            break;   
           
        case PWM_6:
          
            if(s_pPwm_Config_Ptr->ChannelConfig                               \
                [PWM_CHANNEL6].PWM_NOTIFICATION_Channel != NULL)               
            {
                 s_pPwm_Config_Ptr->ChannelConfig                             \
                [PWM_CHANNEL6].PWM_NOTIFICATION_Channel();
            }
            else
            {
                /*Do Nothing */
            }
            
            PIFP_PIFP6 = 1;            
           
            break;   
           
        case PWM_7:
           
            if(s_pPwm_Config_Ptr->ChannelConfig                               \
                [PWM_CHANNEL7].PWM_NOTIFICATION_Channel != NULL)               
            {
                 s_pPwm_Config_Ptr->ChannelConfig                             \
                [PWM_CHANNEL7].PWM_NOTIFICATION_Channel();
            }
            else
            {
                /*Do Nothing */
            }
            
            PIFP_PIFP7 = 1;            
           
            break;    
           
        default:
            break;
    }/*End OF Switch Block */  
   
 
}/*End Of Pwm_EdgeNotification */
But this code is not working as PIFP sets the bits for all enabled PWM channels.Is there any way to solve this problem.
 
Regards,
Satyajit
0 Kudos
Reply

1,722 Views
kef
Specialist I
Two problems with your code. Of course switch-case won't work the way you tried to use it. Switch PIFP, case PWM_0 will be selected only when PIFP reads as 1. Obviously you need to select it when PIFP reads as 1,3,5,7,...255. Just use if(PIFP & (1<<0)){},or simply if(PIFP_PIFP0){}
The second problem is in the way you are clearing port P flags.  
 
    PIFP_PIFP0 = 1; <--- this clears ALL PIFP flags
 
    PIFP = (1<<0);   <---- this clears only PIFP0
 
 
Code:
    if(PIFP_PIFP0)    {          ...        PIFP = (1<<0);                } else if(PIFP_PIFP1)    {          ...            PIFP = (1<<1);     } else if(PIFP_PIFP2)...    ...

 
0 Kudos
Reply

1,723 Views
Lulu
Contributor I
Hi Kef,
 
Thanx for your help.I t is finally working.I just want to know how to calculate PWM output period for a channel.What is channel clock period mentioned in the datasheet of Mc9s12xdp512.Please give an example
 
Regards,
Satyajit
0 Kudos
Reply

1,723 Views
nikosxan
Contributor I
Seems like a good idea (havn't tested thought..)... but i think it should work..... :smileyhappy:
0 Kudos
Reply