For a hardware evaluation project I'm working on, I want to create a device that can be controlled via LabVIEW. LabVIEW can talk to instruments using serial out of the box, and it knows how to talk Standard Commands for Programmable Instruments (SCPI).
In this blog I adapt the LabVIEW Virtual Instrument and the firmware to give direct access to the Hercules PWM Time base control registers. You'll be able to independently set all 7 PWM modules that are available on the controller. |
The FirmWare Support for Direct Register Access
I provided a SCPI command that can receive a numeric value from LabVIEW and write that to the correct PWM module.
Here's the pattern:
{.pattern = "PWM#:TBCTL", .callback = SCPI_HerculesPwmTBCTL,},
The implementation is very simple. Just like in the previous blog, we'll retrieve the PWM module, and the register value, from the SCPI command we get from LabVIEW.
LabView will send something like this:
PWM2:TBCTL #H200
We'll have to derive from this string that the PWM register set we have to address is that of PWM module 2.
And we'll have to write 0x0200 into its TBCTL register.
I have refactored my code since the first blog, to separate the Hercules PWM details from the SCPI parser. And I've factored out some functionality that can be reused accross many functions.
The code to get the right PWM module has gotten its own function:
static scpi_result_t PwmGetModule(scpi_t *context, uint32_t *uModule) { int32_t numbers[1]; // retrieve the PWM channel. Can be 1 - 7 SCPI_CommandNumbers(context, numbers, 1, 1); if (! ((numbers[0] > 0) && (numbers[0] < 8) )) { // todo push error on stack if the PWM CHANNEL not between 1 and 7 return SCPI_RES_ERR; } else { *uModule = numbers[0]; return SCPI_RES_OK; } }
And here's the code that parses ut the register value and sends all to the Hercules PWM side:
/** * Set PWM register TBCTL * * Return SCPI_RES_OK * */ static scpi_result_t SCPI_HerculesPwmTBCTL(scpi_t * context) { int32_t param1; uint32_t uModule; if (PwmGetModule(context, &uModule) == SCPI_RES_ERR) { return SCPI_RES_ERR; } /* read first parameter if present */ if (!SCPI_ParamInt32(context, ¶m1, TRUE)) { return SCPI_RES_ERR; } pwmTBCTL(uModule, param1); return SCPI_RES_OK; }
In that PWM part, I simply write the value to the relevant register of the correct module:
// array of the 7 PWM registers of the RM46 etpwmBASE_t *pwmRegs[7] ={etpwmREG1, etpwmREG2, etpwmREG3, etpwmREG4, etpwmREG5, etpwmREG6, etpwmREG7} ; void pwmTBCTL(uint32_t uModule, uint16_t uValue) { pwmRegs[uModule-1] -> TBCTL = uValue; }
TBCTL is a 16 bit register that drives the following PWM behaviour (and more, that I don't discuss here):
Bit 9 - 7 are the high speed clock divider bits. A few examples
0b111: /14
0b001: /2
0b000: /1
Bit 1 - 0 indicate the counter mode. We'll use these two in our example:
0b00: normal up count
0b11: freeze counter
That's why you'll see the following useful Hex codes on the LabVIEW display below:
PWM 1 MHz: 0
PWM 500 kHz: 80
PWM 125 kHz: 200
PWM of: 3
This register isn't the one where you will later define the exact frequencies. I'll provide additional SCPI functionality to talk to those.
But for the things we want to show here - that we can select to what module we talk, and can push data to a register - TBCTL will do just fine.
The LabVIEW Design
This version of the LabVIEW panel has two user editable controls.
There's a dial that allows you to select PWM module 1 to 7.
When you run the LabVIEW process, it will talk to that PWM module of your Hercules LaunchPad.
The second control is an edit box where you can type the hexadecimal value of what you want to write to that PWM module's TBCTL register.
For convenience, I've added a table with some useful values next to it.
Use this edit box together with your controller's technical reference manual.
The LabVIEW program here is a great tool for you to better learn your controller's PWM module.
You can type in any value you like (better base it on the instructions in the TRM ), and beam them directly into the register.
You can attach a scope and see the results.
Here's the very simple LabVIEW block diagram.
The string constant holds the following value:
PWM%u:TBCTL\s#H%s\n
That is sent into a Format Into String block, together with the values of the dial and the edit control.
At the output of the block, you'll get:
PWM2:TBCTL #H80\n
That is sent off to the Hercules LaunchPad over USB.
The results
Let's see how the outputs of PWM module 1 and 2 look lik when we send a few commands.
After sending 0x3 to both modules (both off):
After sending 0x80 to PWM 2 (500kHz):
After sending 0x0 to PWM 1 (1MHz):
The source for LabVIEW and the Hercules CCS project are attached to this blog. You can try this yourself. |
Top Comments