Writing 0 or period to PWM Compare

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Anonymous
Not applicable

Hi.

   

I'm using the TCPWM component as Center Aligned PWM on 4200M device.

   

In the datasheet there is a note:

   
    

 Note It is not recommended to use the value equal to "0" or equal to "period value" in Center or Asymmetric align PWM modes on the PSoC 4100/PSoC 4200 devices. 

   
   

Does this note relate also to the 4200M devices?

   

I ask because this is exactly what I'm doing in my project - writing the Period value to Compare in order to make the output go Low without stopping the component. 

   

I have some issues with the project. I'm not sure that they are related to this note, but I want to ensure that my implementation is correct.

   

Thanks

0 Likes
1 Solution
MR_41
Employee
Employee
First like received

There are a couple of options to make the PWM output low, while keeping the counter running.

   

Option#1

   

Use the HSIOM_PORT_SELx register to disconnect the pin from the TCPWM output.  Details of this register can be found in the High-Speed I/O Matrix section in the architecture TRM.

   

Option#2

   

In the TCPWM component, enable the "Stop" event and set the Mode to "Level".  Set the stop signal event to "Don't stop on kill".  

   

   

Connect a control register to the stop signal input.  Write a 1 to the control register to make the line and line_n output to go low while the counter keeps running and you keep getting the terminal count events.  

   

   

 

   

   

View solution in original post

0 Likes
16 Replies
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

This is related to the TCPWM component which is the same throughout all PSoC4 family members. Seems to be better to issue a Stop() and Enable API call.

   

 

   

Bob

0 Likes
Anonymous
Not applicable
        Using Stop() is not good for me. I need the PWM counter always running , because I use its TC output for synchronization with other components.   
0 Likes
MR_41
Employee
Employee
First like received

There are a couple of options to make the PWM output low, while keeping the counter running.

   

Option#1

   

Use the HSIOM_PORT_SELx register to disconnect the pin from the TCPWM output.  Details of this register can be found in the High-Speed I/O Matrix section in the architecture TRM.

   

Option#2

   

In the TCPWM component, enable the "Stop" event and set the Mode to "Level".  Set the stop signal event to "Don't stop on kill".  

   

   

Connect a control register to the stop signal input.  Write a 1 to the control register to make the line and line_n output to go low while the counter keeps running and you keep getting the terminal count events.  

   

   

 

   

   

0 Likes
Anonymous
Not applicable

Thank you for your suggestions.

   

I can't use the control register option, because my project is restricted to software only (no UDB usage).

   

The HSIOM_PORT_SELx doesn't seem to work. It disconnects the PWM from the output, but it doesn't seem to reconnect it back, when I try to restore the register setting.

   

In the TRM it's written that the pin's OE can be controlled by firmware, but I can't find how to do this. Maybe it's another option to implement my project.

   

 

   

UPDATE

   

========

   

It seems that the PWM doesn't reconnect because I use Pin_1_Write(0) in initialization.

   

I added this line because without it the output goes high when disconnecting the PWM using the HSIOM_PORT_SELx register, and I need it to go low.

   

Need help with this...

   

(BTW, when I go back to using PWM normally, without HSIOM_PORT_SELx, it seems that Pin_1_Write(0) in initialization somehow disconnects the PWM from the pin - the output is constantly low. But using Pin_1_Write(1) doesn't make the output go constantly high... Am I missing something here...?)

0 Likes
Anonymous
Not applicable

From TRM:

   
    

HSIOM_PORT_SEL1:

    

0x3: DSI_GPIO:
Output is controlled from DSI, but OE is firmware controlled

   
   

How the firmware controls the OE? I can't find it...!

0 Likes
MR_41
Employee
Employee
First like received

You need to worry about OE only if you have enabled OE in the pin.  If you have not enabled OE in the pin (the pin component in the schematics does not have the OE signal), all you need to do is write to HSIOM_PORT_SELx register to make it either a GPIO, or connect to the TCPWM signal.

   

For example, if you want to connect P1_0 to TCPWM output, first configure the pin to strong drive and write a 0.  This is a one time configuration.

   

// Configure P1_0 to Strong drive and set it to LOW
CY_SYS_PINS_SET_DRIVE_MODE(CYREG_GPIO_PRT1_PC, 0, CY_SYS_PINS_DM_STRONG);
CY_SYS_PINS_CLEAR_PIN(CYREG_GPIO_PRT1_PC, 0);

   

To disconnect the PWM from P1_0, write to the HSIOM_PORT_SEL1 register.

   

/* Disconnect P1[0] from TCPWM#2 output and make it a GPIO */
TempVal = CY_GET_REG32(CYREG_HSIOM_PORT_SEL1);
TempVal &= ~0x0000000F;  // Clear Bit#0 to Bit#3 to configure P1[0] as GPIO
CY_SET_REG32(CYREG_HSIOM_PORT_SEL1, TempVal);

   

To connect the PWM to P1_0, write to the HSIOM_PORT_SEL1 register

   

/* Connect P1[0] to TCPWM#2 */
TempVal = CY_GET_REG32(CYREG_HSIOM_PORT_SEL1);
TempVal &= ~0x0000000F;
TempVal |= 0x00000008;
CY_SET_REG32(CYREG_HSIOM_PORT_SEL1, TempVal);

   

Note: I have used direct numbers in the above code.  You can find various macros in cydevice_trm.h file for bit field values (CYVAL_HSIOM_IO0_SEL_ACT_0, CYFLD_HSIOM_IO1_SEL__OFFSET etc.), which you can use for a cleaner coding.

0 Likes
Anonymous
Not applicable

If I enable the OE pin, PSOC Creator instructs me to connect it somewhere. Where can I connect it in order to have a firmware control over it (without using Control Register)?

   

Your suggestion doesn't work for me.

   

My TCPWM is constrained to TCPWM0, by means of directive F(TCPWM,0) in DWR (this is a fix your support team gave me for a problem I had), and the output pin is 6. The correct value for CYREG_HSIOM_PORT_SEL1 register is 3 (this is what I saw while debugging).  It seems that these constraints affect the behavior. Clearing the pin somehow overrides TCPWM connection to it, and the output stays constantly low even after restoring CYREG_HSIOM_PORT_SEL1 value to TCPWM connection (which is 3 in my case). If I delete the directive, it works fine.

0 Likes
lock attach
Attachments are accessible only for community members.
MR_41
Employee
Employee
First like received

Actually, you do not need the OE signal at all.  Just connecting and disconnecting using HSIOM register should work.

   

I did a project to check this concept (project is attached).

   

In this project, I have placed the PWM in TCPWM0 using the directive and have connected the PWM output to P2[4].  In main.c, I am swtiching P2[4] between a GPIO and TCPWM every 100ms, and I can see the output switching (picture below).

   

As I do not have a board with 4200M device, I checked this concept with a 4200.  I am sure this will work with 4200M as well.  Can you have a look at the project and check if this is what you are doing?  You could also change the device in this project for your target device and check if it works.

   

Which is the exact part number that you use in the 4200M series?

   

   

0 Likes
Anonymous
Not applicable

You are missing a point here...

   

The reason that your implementation works is because pin P2[4] is dedicated to TCPWM0.

   

Try moving the pin to P2[2] and changing the code accordingly. It won't work (I've tested it on CY8CKIT-043), because this pin is dedicated to TCPWM5. Even if you change the pin setting in CYREG_HSIOM_PORT_SEL2 to 3 (which is what happens when you connect PWM output to a non-TCPWM-dedicated pin - it is routed using the DSI, so the pin is configured as 3 in CYREG_HSIOM_PORT_SELx).

   

Then change the directive to TCPWM5 - and it will work with P2[2].

0 Likes
MR_41
Employee
Employee
First like received

Sincere apologies.  I had indeed missed the point about the TCPWM connected to a non-dedicated GPIO pin through the DSI logic.

   

I tested the project by routing the TCPWM signal to a non-dedicated pin, I could reproduce your issue.  Writing 0 to the pin using Pin_Write function results in the pin not getting connected to the PWM, and if Pin_Write function is not used, the output is HIGH which is the default state.

   

How about this?  Instead of writing a 0 to the pin and disconnecting it from TCPWM using the HSIOM_PORT_SELx register, just switch the drive mode of the pin between HighZ and Strong.

   

PWM_OUT_SetDriveMode(PWM_OUT_DM_DIG_HIZ);
PWM_OUT_SetDriveMode(PWM_OUT_DM_STRONG);

   

I tested this method and it works.  You will need an external pull down resistor on the pin to keep the pin low when it becomes HighZ.

   

The other option is to enable OE signal for the pin and find out how to control this in firmware.

   

In the architecture TRM, in the UDB chapter, under Port Adapter Block section, there are details of how the OE signal can be controlled using some registers.

   

For each port, there are 4 OE signals coming from the DSI.  Each of these OE signals can be configured to be transparent, single sync, logic high or logic low using the UDB_PAx_CFG14 register.

   

Each of the port pins can connect to one of these OE signals.  This is configured using the UDB_PAx_CFG12 and UDB_PAx_CFG13 registers.

   

However, I did some debugging and could not find these registers controlling the OE signal.  This may need some more digging into the TRM.

0 Likes
Anonymous
Not applicable

I've tried your SetDriveMode() suggestion on CY8CKIT-043 and it works.

   

What's funny is that PWM_OUT_Write(0) overrides this behavior (do you know why?) , so I had to delete it from the code.

   

Thank you.

0 Likes
Anonymous
Not applicable

Actually, I would prefer to control the output without using OE, because I want the output to always be Strong Drive.

   

Using CYREG_HSIOM_PORT_SELx seems like a good idea, if only Pin_Write() wouldn't override it...

   

Is this possible somehow?

0 Likes
Anonymous
Not applicable

I've implemented your Control Register suggestion in my project, just on a trial basis, and it seems that this way it works much smoother than with using Drive Mode. But as I've mentioned, I can't use UDBs in this project. Is there a way to implement this (using the Stop signal) with firmware only?

   

Thanks.

0 Likes
MR_41
Employee
Employee
First like received

Found a solution for this.  The Stop signal state for the TCPWM can be controlled without any UDB or DSI by writing to the CNT_STOP_SEL bits in the TCPWM_CNTx_TR_CTRL0 register.

   

In the schematic, enable the stop signal, set the trigger mode to "Level", set stop signal event to "Dont stop on kill", and connect a logic 1 to the stop input.  This will start the PWM with output low.  

   

Write a 0 to the CNT_STOP_SEL bits to make the stop input logic 0.  And the PWM output will be available on the pin.

   

I used the below code in my test project and am able to stop the PWM output and start it without having to change the pin drive mode or pin state.

   


/* Set the CNT_STOP_SEL bits to 0 which selects a logic 0 as Stop input */
TempVal = CY_GET_REG32(CYREG_TCPWM_CNT0_TR_CTRL0);
TempVal &= ~0x0000F000;
CY_SET_REG32(CYREG_TCPWM_CNT0_TR_CTRL0, TempVal);


/* Set the CNT_STOP_SEL bits to 1 which selects a logic 1 as Stop input */
TempVal =CY_GET_REG32(CYREG_TCPWM_CNT0_TR_CTRL0);
TempVal |= 0x00001000;
CY_SET_REG32(CYREG_TCPWM_CNT0_TR_CTRL0, TempVal);


I did not check if the TC output keep occuring (I am sure that should work fine).  Please try this and let me know if this works for you.

0 Likes
Anonymous
Not applicable

Connecting logic 1 to Stop signal - doesn't work (the output is low).

   

Connecting logic 0 to Stop signal - works like a charm.

   

Thank you very much.

   

By the way, where did you find a list of CNT_STOP_SEL field values? In the TRM it only says "Selects one of the 16 input triggers as a stop trigger", but I couldn't find an explanation which triggers are possible.

0 Likes
MR_41
Employee
Employee
First like received

Great. Glad it worked!

   

 

   

Even I was first looking for the values for the CNT_STOP_SEL field in the register TRM.  But as it was not listed there, I just connected a logic 1 to the Stop signal, built and programmed, and read the register value using debugger.  Then I connected a logic 0 to the stop signal, built and programmed, and read the register value using debugger.  

   

 

   

Will check why this information is left out of the register TRM.

0 Likes