|
|
View previous topic :: View next topic |
Author |
Message |
Leef_me
Joined: 14 Mar 2006 Posts: 45
|
Single output & pulse steering mode on PIC18F24k20 |
Posted: Fri Dec 04, 2009 4:07 am |
|
|
I'm using the PIC18F24k20 with internal oscillator @ 1mhz
I wanted to use the "Single output: P1A, P1B, P1C and P1D controlled by steering (See Section 16.4.7 “Pulse Steering Mode”)
as listed in 16.0 ENHANCED CAPTURE/COMPARE/PWM (ECCP) MODULE
But I am having trouble enabling multiple outputs.
Actually I am having trouble enabling any other output than P1A.
I have the 4 outputs tied together with binary weighted resistors. Sort-of a crude DAC.
Without a load I would expect to see the combined output at Vdd.
Instead I see a voltage that looks like some of the outputs are low.
Thanks in advance.
Leef_me
Code: |
#include <18F24K20.h>
#define P1A PIN_C2
#define P1B PIN_B2
#define P1C PIN_B1
#define P1D PIN_B4
void main()
{
setup_timer_2(T2_DIV_BY_1,24,1);
set_pwm1_duty(10);
// I originally tried this line, but I am somewhat confused by 'PWM_H_H'
// setup_ccp1(CCP_PWM_H_H
setup_ccp1(CCP_PWM
| CCP_PULSE_STEERING_A
| CCP_PULSE_STEERING_B
| CCP_PULSE_STEERING_C
| CCP_PULSE_STEERING_D
);
// the above works, I get a signal on P1A, but if I add any of these code lines
// the combined output appears to be a voltage divider
output_drive(P1B);
bit_set(LDR_TRISB,2); //#define P1B PIN_B2
output_drive(P1C);
bit_set(LDR_TRISB,1); //#define P1C PIN_B1
output_drive(P1D);
bit_set(LDR_TRISB,4); //#define P1D PIN_B4
// at first these seem illogical to use, but I thought the steering bits
would override the data bit and the result would be setting the TRIS bity as output.
output_low(P1B);
output_low(P1C);
output_low(P1D);
} |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Dec 04, 2009 1:10 pm |
|
|
1. Post a test program that compiles without errors. Show the #fuses
and #use delay() statements. If you have a while(1) statement at
the end or some other loop (to prevent the PIC from going to sleep
when it falls off the end of main), then post that.
2. Post your compiler version. |
|
|
Leef_me
Joined: 14 Mar 2006 Posts: 45
|
|
Posted: Fri Dec 04, 2009 4:21 pm |
|
|
Hi PCM,
Sorry about that, I forgot the drill. Here is an updated listing w/all requested info.
Code: | //Compiler version 4.099
// Comment OUT the following "#define" line to allow STAND-ALONE device operation
#define ICD_EN // this allows the #device ICD=TRUE and #FUSES to be placed in the header file
//==========================================================================
// this section is normally stored in the project's *.h file
#include <18F24K20.h>
#ifdef ICD_EN
#device ICD=TRUE
#FUSES NODEBUG //No Debug mode for ICD
#endif
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES INTRC_IO //Internal RC Osc, no CLKOUT
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOBROWNOUT //No brownout reset
#FUSES BORV18
#FUSES NOPUT //No Power Up Timer
#FUSES NOCPD //No EE protection
#FUSES STVREN //Stack full/underflow will cause reset
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT //Program memory not write protected
#FUSES NOWRTD //Data EEPROM not write protected
#FUSES IESO //Internal External Switch Over mode enabled
#FUSES FCMEN //Fail-safe clock monitor enabled
#FUSES PBADEN //PORTB pins are configured as analog input channels on RESET
#FUSES NOWRTC //configuration not registers write protected
#FUSES NOWRTB //Boot block not write protected
#FUSES NOEBTR //Memory not protected from table reads
#FUSES NOEBTRB //Boot block not protected from table reads
#FUSES NOCPB //No Boot Block code protection
#FUSES LPT1OSC //Timer1 configured for low-power operation
#FUSES MCLR //Master Clear pin enabled
#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES NODELAYINTOSC
#use delay(clock=1000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=CONSOLE)
// the above section is normally stored in the project's *.h file
//==========================================================================
#define P1A PIN_C2
#define P1B PIN_B2
#define P1C PIN_B1
#define P1D PIN_B4
#byte LDR_TRISA = 0xF92
#byte LDR_TRISB = 0xF93
#byte LDR_TRISC = 0xF94
void main()
{
setup_timer_2(T2_DIV_BY_1,24,1);
set_pwm1_duty(10);
// I originally tried this line, but I am somewhat confused by 'PWM_H_H'
// setup_ccp1(CCP_PWM_H_H
setup_ccp1(CCP_PWM
| CCP_PULSE_STEERING_A
| CCP_PULSE_STEERING_B
| CCP_PULSE_STEERING_C
| CCP_PULSE_STEERING_D
);
// the above works, I get a signal on P1A,
while(1);
//but if I add any of these code lines
// the combined output appears to be a voltage divider
output_drive(P1B);
bit_set(LDR_TRISB,2); //#define P1B PIN_B2
output_drive(P1C);
bit_set(LDR_TRISB,1); //#define P1C PIN_B1
output_drive(P1D);
bit_set(LDR_TRISB,4); //#define P1D PIN_B4
while(1);
// at first these seem illogical to use, but I thought the steering bits
//would override the data bit and the result would be setting the TRIS bit as output.
output_low(P1B);
output_low(P1C);
output_low(P1D);
while(1);
} |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Dec 04, 2009 5:27 pm |
|
|
It's a little difficult for me to understand how to fix your problem
because I don't understand exactly what you want.
From my point of view, I would make an absolutely stripped down
program, with minimal fuses, no TRIS settings, or output drive and
all this stuff. I would remove all external circuits, such as your
resistor network.
Then I would try to set it up for PWM single channel, with the same
signal being output to all 4 pins, or to smaller combinations of the pins.
If I did that, then I would pronounce that I had success. I would
understand how to make it do pulse steering.
But I'm not sure that's what you want. So it's difficult for me to proceed. |
|
|
Leef_me
Joined: 14 Mar 2006 Posts: 45
|
|
Posted: Fri Dec 04, 2009 6:04 pm |
|
|
I want the code needed to use the "Single output: P1A, P1B, P1C and P1D controlled by steering (See Section 16.4.7 “Pulse Steering Mode”)
as listed in 16.0 ENHANCED CAPTURE/COMPARE/PWM (ECCP) MODULE
As I understand it, it is possible to have a single PWM output and then use steering to send that output to any one of four outputs.
For example Ttelmah's 3rd post, and PCM programmer's 2nd post and PCM's last post in this thread
http://www.ccsinfo.com/forum/viewtopic.php?p=82431
Hey! Wait a minute. There seems to be a different number of parameters !?!?! Or'ing doesn't count as another parameter !
PCM wrote
Code: |
setup_ccp1(CCP_PWM, CCP_PWM_H_H |CCP_PULSE_STEERING_B);
|
Leef_me wrote
Code: |
setup_ccp1(CCP_PWM
| CCP_PULSE_STEERING_A
| CCP_PULSE_STEERING_B
| CCP_PULSE_STEERING_C
| CCP_PULSE_STEERING_D
); |
|
|
|
Leef_me
Joined: 14 Mar 2006 Posts: 45
|
|
Posted: Fri Dec 04, 2009 10:29 pm |
|
|
Bump, no improvement
Anyone else have corrections for Pic18F24K20 single PWM steered to multiple outputs ? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Dec 05, 2009 12:14 am |
|
|
I think there are some bugs in the PWM steering code in vs. 4.099
(and they're also in vs 4.101). The test program shown below should
fix those bugs. I've created a new routine called set_pwm_steering().
Basically, I've separated setting the PWM and setting the steering into
two different functions now. That way I can fix the steering code
problems by writing my own routine to do it. It uses the same PWM
steering constants that are in the 18F24K20.H file, so it's easy to use.
I don't have this PIC so I can't test it in hardware, but I think it should
work.
Code: |
#include <18F24K20.h>
#fuses INTRC_IO, NOWDT, PUT, NOLVP, NOPBADEN
#use delay(clock=8000000)
// These are the PWM output pins for the 18F24K20.
#define P1A PIN_C2
#define P1B PIN_B2
#define P1C PIN_B1
#define P1D PIN_B4
#byte PSTRCON = 0xFB9
// Call this routine to set the PWM steering. You can OR
// together the PWM steering constants from the PIC's
// header file.
void set_pulse_steering(int32 steering)
{
int8 temp;
temp = make8(steering, 3); // Get high byte only
PSTRCON = temp; // Setup PWM steering register
// Set the TRIS to outputs for the enabled steering pins.
// Also set the selected pins to a low level.
if(temp & 1)
output_low(P1A);
if(temp & 2)
output_low(P1B);
if(temp & 4)
output_low(P1C);
if(temp & 8)
output_low(P1D);
}
//===========================================
void main()
{
setup_timer_2(T2_DIV_BY_16, 124, 1); // Set 1000 Hz PWM freq
set_pwm1_duty(31); // Set PWM for 25% duty cycle
// Set up PWM so that all four outputs are active high.
setup_ccp1(CCP_PWM_H_H);
// Enable PWM output on all four pins.
set_pulse_steering( CCP_PULSE_STEERING_A |
CCP_PULSE_STEERING_B |
CCP_PULSE_STEERING_C |
CCP_PULSE_STEERING_D);
while(1);
} |
|
|
|
Leef_me
Joined: 14 Mar 2006 Posts: 45
|
|
Posted: Sat Dec 05, 2009 3:01 am |
|
|
Thanks PCM,
I'll have to try out your code.
>>I think there are some bugs in the PWM steering code in vs. 4.099
edit: BTW, how did you know about the above bug ?
What led you to come across this and find out the details ?
Yes, after a few hours I found that "PSTRCON @ 0xFB9" is never mentioned in the LST file.
as a result instead of getting for example:
STRB: Steering Enable bit B
this ---> 1 = P1B pin has the PWM waveform with polarity control from CPxM<1:0>
I was getting
this ---> 0 = P1B pin is assigned to port pin
>>It uses the same PWM steering constants that are in the 18F24K20.H file, so it's easy to use.
great idea!
IMHO as a purist, it might be more "proper" to write
output_drive(P1A);
instead of
output_low(P1A); |
|
|
Leef_me
Joined: 14 Mar 2006 Posts: 45
|
|
Posted: Mon Dec 07, 2009 6:34 pm |
|
|
from: CCS Support
>The problem you reported has been fixed and will be in the next compiler release.
(12/07/2009 1:05 PM pacific)
>> Leef_me wrote:
>>
>> There appears to be a problem with 'setup_ccp1' single PWM output pulse steering
>> The steering register is not updated by the instruction.
>> setup_ccp1(CCP_PWM |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Dec 08, 2009 6:19 pm |
|
|
Quote: |
BTW, how did you know about the above bug ?
What led you to come across this and find out the details ?
|
I compiled a test program and looked at the .LST file. With vs. 4.099,
I noticed the code looked incorrect at the end of the routine. It should
load a value into the PSTRCON register. Instead, it's doing something
strange with a banked register.
I remembered that the 16F690 also had PWM pulse steering. So I
compiled a test program for it and looked at the code, as shown below.
Notice that they set two bank select bits and write to a register at address
0x19D. So it became clear that CCS had just copied the 16F code into
the 18F compiler for this feature. They didn't change the address of
the PSTRCON register to the correct 18F address.
Also, they are supposed to set the TRIS to be outputs for all the pins
that are set for PWM steering. They don't do that. They only do it
for the first one.
After I saw all of this, then I posted "I think there are some bugs".
18F14K20 With vs. 4.099:
Code: | .................... // Steer the PWM output to all four P1x pins.
.................... setup_ccp1(CCP_PWM_H_H | CCP_PULSE_STEERING_A
.................... | CCP_PULSE_STEERING_B
.................... | CCP_PULSE_STEERING_C
.................... | CCP_PULSE_STEERING_D );
0042: BCF TRISC.2
0044: BCF LATC.2
0046: MOVLW 0C
0048: MOVWF CCP1CON
004A: CLRF PWM1CON
004C: CLRF ECCP1AS
004E: MOVLW 0F // *** Bug
0050: MOVLB 1 // *** Bug
0052: MOVWF x9D // *** Bug
|
16F690 with vs. 4.099:
Code: |
.................... setup_ccp1(CCP_PWM | CCP_PULSE_STEERING_A
.................... | CCP_PULSE_STEERING_B
.................... | CCP_PULSE_STEERING_C
.................... | CCP_PULSE_STEERING_D
.................... );
0026: BSF 03.5
0027: BCF 07.5
0028: BCF 03.5
0029: BCF 07.5
002A: BSF 03.5
002B: BCF 09.6
002C: MOVLW 0C
002D: BCF 03.5
002E: MOVWF 17
002F: CLRF 1C
0030: CLRF 1D
0031: MOVLW 0F
// This is the 16F690 code that writes to its PSTRCON register.
// The address is 0x19D.
0032: BSF 03.5
0033: BSF 03.6
0034: MOVWF 1D
|
18F14K20 with vs. 4.102:
Code: | .................... setup_ccp1(CCP_PWM_H_H | CCP_PULSE_STEERING_A
.................... | CCP_PULSE_STEERING_B
.................... | CCP_PULSE_STEERING_C
.................... | CCP_PULSE_STEERING_D );
0042: BCF TRISC.2
0044: BCF LATC.2
0046: BCF F96.6 // Set TRISE.6 = 0 *** Possible new bug
0048: MOVLW 0C
004A: MOVWF CCP1CON
004C: CLRF PWM1CON
004E: CLRF ECCP1AS
0050: MOVLW 0F // *** Fixed
0052: MOVWF PSTRCON // *** Fixed
|
They still don't set the TRIS for all the Pulse Steering pins. You have
to set it manually with your own code. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|