View previous topic :: View next topic |
Author |
Message |
dmitrboristuk
Joined: 26 Sep 2020 Posts: 55
|
PSMC in PIC16F1788 |
Posted: Thu Feb 04, 2021 11:17 am |
|
|
Hello everybody!
Prompt a function to write a value to a register PSMCxSTR0 for steering PWM on outputs A, B,C, D. I could not find such a function in the compiler manual. |
|
|
dyeatman
Joined: 06 Sep 2003 Posts: 1933 Location: Norman, OK
|
|
Posted: Thu Feb 04, 2021 11:44 am |
|
|
What version compiler and what PIC are you using?
With CCS you don't have to access the registers directly.
Why dont you use the PWM capability built into CCS and let
the compiler do the work?
The PWM functions are documented in the manual and the PWM header files. _________________ Google and Forum Search are some of your best tools!!!! |
|
|
dmitrboristuk
Joined: 26 Sep 2020 Posts: 55
|
|
Posted: Thu Feb 04, 2021 11:52 am |
|
|
I am using version 5.49. I need PWM on 4 channels with independent control. I think that PIC16F1789 is very suitable for this. I found all the necessary functions, they are in the manual. But there is no function to control PSMCxSTR0 |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9221 Location: Greensville,Ontario
|
|
Posted: Thu Feb 04, 2021 2:36 pm |
|
|
re: But there is no function to control PSMCxSTR0
it may have been an oversight (it is a complicated peripheral ! )but you can control those bits of those registers 'manually'. |
|
|
dmitrboristuk
Joined: 26 Sep 2020 Posts: 55
|
|
Posted: Thu Feb 04, 2021 11:56 pm |
|
|
Tell me how can I write data to a register. Are there any special functions for this. Does ccs c support referring to named special registers (e.g. TMR1, STATUS) |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Feb 05, 2021 12:18 am |
|
|
dmitrboristuk wrote: | Tell me how can I write data to a register. |
Example:
Code: |
#include <16F1789.h>
#use delay(internal=4M)
// Get register address from CCS database:
#byte PSMC1STR0 = getenv("SFR:PSMC1STR0")
#byte PSMC1STR1 = getenv("SFR:PSMC1STR1")
// Manually assign register address (by reading PIC data sheet).
// Do it this way if CCS database is incorrect or not complete.
#byte PSMC1POL = 0xE96
//==============================================
void main(void)
{
PSMC1STR0 = 0x03;
while(TRUE);
} |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19499
|
|
Posted: Fri Feb 05, 2021 1:06 am |
|
|
The PSMCxSTR0 register, is set for you by the psmc_pins command.
If you set:
psmc_pins(1, PSMC_A|PSMC_B);
This turns on the bits for PSMC1A and PSMC1B in this register.
For some (annoying) reason, the assembler doesn't put the register
name in, but a quick test shows:
Code: |
.............................. psmc_pins(1, PSMC_A|PSMC_B);
0082: MOVLW 03
0083: MOVWF 2E //This is actually accessing the STR0 register
//If you look the bank is set to 0x1D, and byte 2E of bank 29, is
//PSMC1STR0
0084: MOVWF PSMC1OEN
0085: CLRF PSMC1POL
0086: MOVLB 01
0087: BCF TRISC.TRISC0
0088: BCF TRISC.TRISC1
0089: MOVLB 1D
008A: BCF 2F.7
008B: BSF PSMC1CON.PSMC1EN
008C: BSF PSMC1CON.PSMC1LD
|
You just OR together the PSMC pins you want enabled. |
|
|
dmitrboristuk
Joined: 26 Sep 2020 Posts: 55
|
|
Posted: Fri Feb 05, 2021 1:08 am |
|
|
Thank you! soon i will try it
As far as I understand correctly, PSMC1STR0 and psmc_pins (1, PSMC_A | PSMC_B) are different things in principle. PSMC1STR0 is needed to get modulation control without glitches.
Ttelmah
How did you manage to configure the compiler so that named special registers are displayed in the assembler code ? Version Compiler? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19499
|
|
Posted: Fri Feb 05, 2021 1:45 am |
|
|
Options
Project
Output Files
Then in the column 'List File', tick the box 'Symbolic' and apply.
PSMC1STR0, doesn't have anything to do with glitches. It just sets the
output steering. The only time is affects glitches, is that you have to ensure
this is set correctly before you trigger the PSMCxLD or PSMCxEN, when
using 'synchronised steering', or you can generate a glitch, since this
updates immediately overriding the synchronisation. |
|
|
dmitrboristuk
Joined: 26 Sep 2020 Posts: 55
|
|
Posted: Fri Feb 05, 2021 2:02 am |
|
|
Thank you
Perhaps I put it wrong. I will explain what I need. I want the output to be free of torn modulating pulses at the beginning and end of the pulse train. At the moment I do not have a controller to physically see the work. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19499
|
|
Posted: Fri Feb 05, 2021 2:36 am |
|
|
To enable the synchronisation (which is handled by PSMCxSTR1, not STR0),
or this into the setting:
psmc_pins(1, PSMC_A|PSMC_ON_NEXT_PERIOD);
Then to move this pulse to the B output, on the next pulse, use:
psmc_pins(1, PSMC_B|PSMC_ON_NEXT_PERIOD);
This re-routes the output to the B pin, rather than the A pin, but does
the change, when the clock next resets. So pulses are always complete
on the change.
The PWM itself will never generate 'torn' pulses, unless you do something
like changing the steering. Things like period updates always synchronise
to the next clock reset. |
|
|
dmitrboristuk
Joined: 26 Sep 2020 Posts: 55
|
|
Posted: Fri Feb 05, 2021 3:07 am |
|
|
Thank you for your detailed answer. I will try to do this. As for the PIŠ”16F1789 controller, I have several questions.
By datasheet
page 14 in controller 4 of the PSMC module
pages 11 - 12 1 module 6 outputs
2 module 2 outputs
3 module 6 outputs
4 module 2 outputs
page 45 PSMC1STR0 6 outputs
page 46 PSMC2STR0 2 outputs
page 47 PSMC3STR0 2 outputs
page 48 PSMC1STR0 2 outputs
How many outputs do blocks have in reality? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19499
|
|
Posted: Fri Feb 05, 2021 6:26 am |
|
|
In 'standard PWM mode', there is just one signal from each module.
You can send this to multiple pins.
Look at the pin details 'Table-1'. On the 28pin package, PSMC1 has A,B,C,D,
E & F pins available.
PSMC2, 3 & 4, each only offer A & B pins.
Several of the pins are shared between these modules, so you have
have just eight pins that can be driven from the modules, when all are
in use.
It's basically designed so you have have two complementary outputs from
each module. Only module 1, offers instead the ability to do things like
full bridge with four outputs (and complementary on two). These modes
don't support 'steering' though. The outputs only come on the defined
pins when running like this. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9221 Location: Greensville,Ontario
|
|
Posted: Fri Feb 05, 2021 8:53 am |
|
|
re: Quote: | I need PWM on 4 channels with independent control. | Depending on what else is needed, it might be easier/cheaper to have 4 small 'slave' PICs being controlled from a 'master' PIC.
'independent' control implies that they are not 'synchronised' PWM....
Also 'how fast' is needed for the PWM ? There are some nice SW generated PWM code for RGB LEDs....
so a lot depends on actual requirements of the project. |
|
|
dmitrboristuk
Joined: 26 Sep 2020 Posts: 55
|
|
Posted: Fri Feb 05, 2021 2:45 pm |
|
|
In Proteus 8, PSMC 3 does not work and therefore it was not possible to find out how many outputs 2 or 6 there are. I tried the two steering options offered to me. In my opinion, control through the PSMCxSTR0 register is more convenient and simple. For example:
Code: |
#include <16f1789.h>
#use delay(osc=20mhz)
#byte PSMC1STR0 = 0xEAE //1 EAE, 2 ECE, 4 F2E, 3 EEE
#define us(time) (int16)(time*(getenv("CLOCK")/1000000))
int8 i = 0;
#int_ext
void isrext()
{
i++;
if (i > 7)
i = 0;
PSMC1STR0 = i;
}
void main(void) {
setup_psmc(
1,
PSMC_SINGLE | PSMC_ENABLE_NOW,
PSMC_EVENT_TIME | PSMC_SOURCE_FOSC | PSMC_DIV_2,
us(50),
PSMC_EVENT_TIME,
us(5),
PSMC_EVENT_TIME,
us(25)
);
psmc_pins(
1,
PSMC_A | PSMC_B | PSMC_C | PSMC_D | PSMC_E | PSMC_F
);
enable_interrupts(INT_EXT_L2H);
enable_interrupts(global);
while(1 != 0 )
{
}
}
| [/img] |
|
|
|