Pwm with open drain function

cancel
Showing results for 
Search instead for 
Did you mean: 

Pwm with open drain function

492 Views
NXP Employee
NXP Employee
Content originally posted in LPCWare by cto4260 on Thu May 21 07:40:45 MST 2015
Hey,

i want to create a PWM Signal with open drain output at the Pin P1[18] on my LPC1769.

When I configure a normal PWM Signal it works very good, but when I configure the Pin as open drain, nothing changes..
For setting the Open drain function I am using the function from LPCOpen.

Is it possible to create an open drain PWM signal and if, what is my fault?

I want to control a servo, which needs a PWM with 5V. The PWM cable has a 5V Pull up.

thanks,
Marvin
Labels (1)
0 Kudos
8 Replies

86 Views
NXP Employee
NXP Employee
Content originally posted in LPCWare by cto4260 on Sat May 30 10:08:51 MST 2015
thank you for your help.
The Servo accepts a 3,3V PWM, so I used a normal PWM and everything works.
0 Kudos

86 Views
NXP Employee
NXP Employee
Content originally posted in LPCWare by IanB on Sat May 30 09:57:29 MST 2015
Just put a schottky diode in series. . .

but actually, as the 1769 has 5V tolerant pins, then driving it to 3.3V won't do anything any harm, even if it already has a pull-up. The servo probably has a threshold of 2.4V, which you will easily achieve by driving it to 3.3V, and doing so give a sharper edge with faster rise time.
0 Kudos

86 Views
NXP Employee
NXP Employee
Content originally posted in LPCWare by LabRat on Thu May 28 16:50:22 MST 2015

Quote: cto4260
...in pwmUpTime and pwmDownTime i can write everything, but the the signal is everytime the same...



You are trying to use PWM like a simple timer. That's not working  :((

The idea to change match registers in a cycle contradicts the shadow register mechanism  :O

UM:

Quote:
24.6.7 PWM Latch Enable Register (PWM1LER - 0x4001 8050)
The PWM Latch Enable Registers are used to control the update of the PWM Match registers when they are used for PWM generation. [color=#f00]When software writes to the location of a PWM Match register while the Timer is in PWM mode, the value is captured, but not used immediately.[/color]
[color=#f00]When a PWM Match 0 event occurs (normally also resetting the timer in PWM mode), the contents of shadow registers will be transferred to the shadow registers if the corresponding bit in the Latch Enable Register has been set.[/color] At that point, the new values will take effect and determine the course of the next PWM cycle. Once the transfer of new values has taken place, all bits of the LER are automatically cleared. Until the corresponding bit in the PWMLER is set and a PWM Match 0 event occurs, any value written to the PWM Match registers has no effect on PWM operation.



I would recommend to use PWM as PWM  :)
0 Kudos

86 Views
NXP Employee
NXP Employee
Content originally posted in LPCWare by R2D2 on Thu May 28 14:00:04 MST 2015

Quote: cto4260
At the buttom you can See my Code. It doesn't work very good.


Probably because there's no main  :D


Quote: cto4260

Can you help me?



Could be useful to post a complete project  :)
0 Kudos

86 Views
NXP Employee
NXP Employee
Content originally posted in LPCWare by R2D2 on Thu May 28 14:00:01 MST 2015

Quote: cto4260
At the buttom you can See my Code. It doesn't work very good.


Probably because there's no main  :D


Quote: cto4260

Can you help me?



Could be useful to post a complete project  :)
0 Kudos

86 Views
NXP Employee
NXP Employee
Content originally posted in LPCWare by cto4260 on Thu May 28 12:45:36 MST 2015
Hey,
i started to wirte a PWM function with the interrupt handler and the Output Pin defined as Open Drain GPIO

At the buttom you can See my Code. It doesn't work very good.
I am becoming a PWM, but it's length isn't variable. in pwmUpTime and pwmDownTime i can write everything, but the the signal is everytime the same.

although the rising edge is not very clear..

Can you help me?

thanks,
marvin


// PWM
volatile uint32_tpwmUpTime[6] = { 0, 0, 0, 0, 0, 500000 };
volatile uint32_tpwmDownTime[6] = { 0, 0, 0, 0, 0, 500000 };


//Tacho
uint8_t tachoMuxChannels[TACHO_MUX_NUM] = {TACHO_MUX_PUMP_LEFT, TACHO_MUX_PUMP_RIGHT, TACHO_MUX_FLOW_LEFT, TACHO_MUX_FLOW_RIGHT};
extern uint8_t tachoEdgesRising;

// temperature before and after cooling element in left and right cooling circuit
extern uint16_t tempLeftIn,
tempLeftOut,
tempRightIn,
tempRightOut;

enum CoolingState
{
hold= 0,
faster= 1,
slower= 2,
warning= 3
} CoolingStateLeft = 0, CoolingStateRight = 0;


typedef struct {
__IO uint32_t IR;
__IO uint32_t TCR;
__IO uint32_t TC;
__IO uint32_t PR;
__IO uint32_t PC;
__IO uint32_t MCR;
__IO uint32_t MR0;
__IO uint32_t MR1;
__IO uint32_t MR2;
__IO uint32_t MR3;
__IO uint32_t CCR;
__I uint32_t CR0;
__I uint32_t CR1;
__I uint32_t CR2;
__I uint32_t CR3;
__I uint32_t RESERVED0;
__IO uint32_t MR4;
__IO uint32_t MR5;
__IO uint32_t MR6;
__IO uint32_t PCR;
__IO uint32_t LER;
    __I uint32_t RESERVED1[7];
__IO uint32_t CTCR;
} LPC_PWM_T;




volatile uint8_t i = 0;
volatile static uint32_t pwmOut[6] = { 0, 0, 0, 0, 0, 0 };
void PWM1_IRQHandler(void)
{
uint32_t intFlags = 0;
intFlags = LPC_PWM1->IR;
uint32_t time = LPC_PWM1->TC;

if(intFlags & 0b1)
{
intFlags = intFlags & ~(0b1);
pwmOut[0] = !pwmOut[0];
if(pwmOut[0] == 0)
LPC_PWM1->MR0 = time + pwmDownTime[0];
else if(pwmOut[0] == 1)
LPC_PWM1->MR0 = time + pwmUpTime[0];
Chip_GPIO_SetPinState(LPC_GPIO, 1, 26, pwmOut[0]);
}
if(intFlags & 0b10)
{
intFlags = intFlags & ~(0b10);
pwmOut[1] = !pwmOut[1];
if(pwmOut[1] == 0)
LPC_PWM1->MR1 = time + pwmDownTime[1];
else if(pwmOut[1] == 1)
LPC_PWM1->MR1 = time + pwmUpTime[1];
Chip_GPIO_SetPinState(LPC_GPIO, 1, 24, pwmOut[1]);
}
if(intFlags & 0b100)
{
intFlags = intFlags & ~(0b100);
pwmOut[2] = !pwmOut[2];
if(pwmOut[2] == 2)
LPC_PWM1->MR2 = time + pwmDownTime[2];
else if(pwmOut[0] == 1)
LPC_PWM1->MR2 = time + pwmUpTime[2];
Chip_GPIO_SetPinState(LPC_GPIO, 1, 23, pwmOut[2]);
}
if(intFlags & 0b1000)
{
intFlags = intFlags & ~(0b1000);
pwmOut[3] = !pwmOut[3];
if(pwmOut[1] == 0)
LPC_PWM1->MR3 = time + pwmDownTime[3];
else if(pwmOut[1] == 1)
LPC_PWM1->MR3 = time + pwmUpTime[3];
Chip_GPIO_SetPinState(LPC_GPIO, 1, 21, pwmOut[3]);
}
if(intFlags & 0b100000000)
{
intFlags = intFlags & ~(0b100000000);
pwmOut[4] = !pwmOut[4];
if(pwmOut[4] == 4)
LPC_PWM1->MR4 = time + pwmDownTime[4];
else if(pwmOut[0] == 1)
LPC_PWM1->MR4 = time + pwmUpTime[4];
Chip_GPIO_SetPinState(LPC_GPIO, 1, 20, pwmOut[4]);
}
if(intFlags & 0b1000000000)
{
intFlags = intFlags & ~(0b1000000000);
pwmOut[5] = !pwmOut[5];
if(pwmOut[5] == 0)
LPC_PWM1->MR5 = time + pwmDownTime[5];
else if(pwmOut[5] == 1)
LPC_PWM1->MR5 = time + pwmUpTime[5];
Chip_GPIO_SetPinState(LPC_GPIO, 1, 18, pwmOut[5]);
}
}

void pwmInit(uint8_t uBitPattern)
{
Chip_GPIO_GetPinDIR(LPC_GPIO, 1, 26);// Output for PWM0
Chip_GPIO_GetPinDIR(LPC_GPIO, 1, 24);// Output for PWM1
Chip_GPIO_GetPinDIR(LPC_GPIO, 1, 23);// Output for PWM2
Chip_GPIO_GetPinDIR(LPC_GPIO, 1, 21);// Output for PWM3
Chip_GPIO_GetPinDIR(LPC_GPIO, 1, 20);// Output for PWM4
Chip_GPIO_GetPinDIR(LPC_GPIO, 1, 18);// Output for PWM5

Chip_GPIO_SetPinState(LPC_GPIO, 1, 26, 0);// Reset all Pins
Chip_GPIO_SetPinState(LPC_GPIO, 1, 24, 0);
Chip_GPIO_SetPinState(LPC_GPIO, 1, 23, 0);
Chip_GPIO_SetPinState(LPC_GPIO, 1, 21, 0);
Chip_GPIO_SetPinState(LPC_GPIO, 1, 20, 0);
Chip_GPIO_SetPinState(LPC_GPIO, 1, 18, 0);

Chip_IOCON_EnableOD(LPC_IOCON, 1, 26);// Enable open drain mode for all pins
Chip_IOCON_EnableOD(LPC_IOCON, 1, 24);
Chip_IOCON_EnableOD(LPC_IOCON, 1, 23);
Chip_IOCON_EnableOD(LPC_IOCON, 1, 21);
Chip_IOCON_EnableOD(LPC_IOCON, 1, 20);
Chip_IOCON_EnableOD(LPC_IOCON, 1, 18);


LPC_SYSCTL->PCONP |= (1 << 6);// Enable Clock
LPC_SYSCTL->PCLKSEL[0] |= (3 << 12);// Peripheral Clock Selection for PWM
LPC_PWM1->TCR = (1 << 1);// Reset Timer Counter and PWM Prescale Counter
LPC_PWM1->PR = 1000;// TC is incremented every PR+1 cycles of PCLK
LPC_PWM1->MR0 = pwmDownTime[0];
LPC_PWM1->MR1 = pwmDownTime[1];
LPC_PWM1->MR2 = pwmDownTime[2];
LPC_PWM1->MR3 = pwmDownTime[3];
LPC_PWM1->MR4 = pwmDownTime[4];
LPC_PWM1->MR5 = pwmDownTime[5];
LPC_PWM1->MR6 = 0;// Reset value
LPC_PWM1->MCR = ( (1 << 0)  | (1 << 3) | // Interrupts on PWMMR0, when PWMMR0 matches PWMTC
  (1 << 6)  | (1 << 9) |
  (1 << 12) | (1 << 15) );
LPC_PWM1->PCR = (1 << 9)  | (1 << 10) |// Enable PWM Output (perhaps i have to set it to 0
(1 << 11) | (1 << 12) |
(1 << 13) | (1 << 14);
LPC_PWM1->LER = (1 << 0) | (1 << 1) |// Enable PWM Latch (perhaps i have to set it to 0
(1 << 2) | (1 << 3) |
(1 << 4) | (1 << 5);

NVIC_EnableIRQ(PWM1_IRQn);
}


void pwmStart(uint8_t uBitPattern)
{
LPC_PWM1->TCR = (1 << 0) | (1 << 3);// Enable Counter and Enable PWM

}
0 Kudos

86 Views
NXP Employee
NXP Employee
Content originally posted in LPCWare by R2D2 on Thu May 21 13:15:57 MST 2015

Quote: cto4260
When I configure a normal PWM Signal it works very good, but when I configure the Pin as open drain, nothing changes..



'Open drain mode' is not working with PWM  :((



Quote: cto4260
Is it possible to create an open drain PWM signal...



In your case I would suggest to use a real open drain and add a FET  :)

Of course you can also use open-drain pins P0[27]/P0[28] as GPIO and use PWM interrupts to switch them...
0 Kudos

86 Views
NXP Employee
NXP Employee
Content originally posted in LPCWare by MikeSimmonds on Thu May 21 12:10:30 MST 2015
I don't use LPCOpen, but did you check that the function you use to set open drain mode leaves the function code
for the pin as 'PWM' rather than setting it back to 'GPIO'?

Mike
0 Kudos