![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
Abravius
Joined: 18 May 2022 Posts: 4
|
Why my PIC speed decreasing when i create new variables |
Posted: Wed May 18, 2022 11:58 pm |
|
|
Hi Everyone, I'm not the best in english... I will do my best .
I'm trying to make a driver for the LED WS2812.
For now, I'm using the PIC16F1947 from the Explorer 8 board.
The driver is working correctly as long as I don't create new global variables.
In fact, When I add global variables, The pic speed decreases for a reason I don't understand...
Frame rate with no global variables : 33.20uS
Frame rate with global variables : 53uS
Note that, I'm using Assembler (my first time using Assembler) to send the data over the PIN and some C to prepare the colour.
Here is my code :
Code: | /*
* File: WS2812.h
* Author: rionque
*
* Created on 17. mai 2022, 12:43
*/
// /!\ THIS DRIVER WORKS ONLY WITH A 32MHZ PIC FREQUENCY /!\
//What PIN is used from the C port
#define SELECTED_PORTC_OUTPUT 5
//How many leds on the strip
#define LED_QTY 24
#byte PORTC = 0x00E
#byte LATC = 0x10E
#byte TRISC = 0x08E
//Array that contain the colour of each LED
static int LEDArray[3][LED_QTY];
//Initialisation of the selected PIN from the C port
void Init_NeoPixel()
{
#asm
//Clear all the register for the C port
BCF PORTC, SELECTED_PORTC_OUTPUT;
BCF LATC, SELECTED_PORTC_OUTPUT;
BCF TRISC, SELECTED_PORTC_OUTPUT;
#endasm
}
//Function used set a colour for a specific LED
//<_Led> : Selected LED
//<_R> : Red setting
//<_G> : Green setting
//<_B> : Blue setting
void SetPixelRGB(int _Led, int _R, int _G, int _B)
{
LEDArray[0][_Led] = _R;
LEDArray[1][_Led] = _G;
LEDArray[2][_Led] = _B;
}
//function used set a colour and the brightness for a specific LED
//<_Led> : Selected LED
//<_R> : Red setting
//<_G> : Green setting
//<_B> : Blue setting
//<_Br> : Set the brightness for the selected LED
void SetPixelRGBB(int _Led, int _R, int _G, int _B, int _Br)
{
int Lum = _Br * 0.392156863;
LEDArray[0][_Led] = (_R / 100) * Lum;
LEDArray[1][_Led] = (_G / 100) * Lum;
LEDArray[2][_Led] = (_B / 100) * Lum;
}
//function used for set all the same colour for all the LED
//<_R> : Red setting
//<_G> : Green setting
//<_B> : Blue setting
void FillStrip(int _R, int _G, int _B)
{
for(int i = 0; i < LED_QTY; i++)
{
LEDArray[0][i] = _R;
LEDArray[1][i] = _G;
LEDArray[2][i] = _B;
}
}
//function used for turn off all the LED
void ClearStrip()
{
for(int i = 0; i < LED_QTY; i++)
{
LEDArray[0][i] = 0;
LEDArray[1][i] = 0;
LEDArray[2][i] = 0;
}
}
//Function used for determinate the brightness for all the LED
//<_Brightness> : Brightness setting for all the LED
void BrightnessSet(int _Brightness)
{
int LUM = _Brightness * 0.392156863;
for(int i = 0; i < LED_QTY; i++)
{
LEDArray[0][i] = (LEDArray[i] / 100) * LUM;
LEDArray[1][i] = (LEDArray[i] / 100) * LUM;
LEDArray[2][i] = (LEDArray[i] / 100) * LUM;
}
}
//Function used for set colour for some selected LED
//<_LedMin> : Start LED
//<_LedMax> : Stop LED
//<_R> : Red setting
//<_G> : Green setting
//<_B> : Blue setting
//<_Br> : Brightness setting for all the LED
void SetManyLED(int _LedMin, int _LedMax, int _R, int _G, int _B, int _Br)
{
//THERE IS A PROBLEM, NOT THE NEST METHOD
int LUM = _Br * 0.392156863;
if(_LedMax == 0)
for(int i = _LedMin; i < LED_QTY - _LedMax; i++)
{
LEDArray[0][i] = (_R / 100) * LUM;
LEDArray[1][i] = (_G / 100) * LUM;
LEDArray[2][i] = (_B / 100) * LUM;
}
else
for(int i = _LedMin; i < _LedMax - _LedMax; i++)
{
LEDArray[0][i] = (_R / 100) * LUM;
LEDArray[1][i] = (_G / 100) * LUM;
LEDArray[2][i] = (_B / 100) * LUM;
}
}
//Function used to turn on LED with the specific color defined earlier
void showStrip()
{
int LP0 = 0, LP1 = 0, LP2 = 0;
for(int i = 0; i < LED_QTY; i++)
{
int _G = LEDArray[1][i];
int _R = LEDArray[0][i];
int _B = LEDArray[2][i];
//PARTIE EN ASSEMBLEUR POUR GARANTIR LA VITESSE DE TRAITEMENT EN NANOSECONDE
#asm
///////////////////////////////////////////////////////CONCERNE LA COULEUR VERTE
SUB0:
BTFSC LP0, 3;
GOTO SUB1;
INCF LP0, 1;
BSF PORTC,SELECTED_PORTC_OUTPUT;
NOP;
BTFSS _G, 0; //Condition permettant de déterminer quand la PIN doit être FALSE
BCF PORTC,SELECTED_PORTC_OUTPUT;
BCF PORTC,SELECTED_PORTC_OUTPUT;
RRF _G;
GOTO SUB0;
///////////////////////////////////////////////////////CONCERNE LA COULEUR ROUGE
SUB1:
BTFSC LP1, 3;
GOTO SUB2;
INCF LP1, 1;
BSF PORTC,SELECTED_PORTC_OUTPUT;
NOP;
BTFSS _R, 0; //Condition permettant de déterminer quand la PIN doit être FALSE
BCF PORTC,SELECTED_PORTC_OUTPUT;
BCF PORTC,SELECTED_PORTC_OUTPUT;
RRF _R;
GOTO SUB1;
////////////////////////////////////////////////////////CONCERNE LA COULEUR BLEU
SUB2:
BTFSC LP2, 3;
GOTO SUB3;
INCF LP2, 1;
BSF PORTC,SELECTED_PORTC_OUTPUT;
NOP;
BTFSS _B, 0; //Condition permettant de déterminer quand la PIN doit être FALSE
BCF PORTC,SELECTED_PORTC_OUTPUT;
BCF PORTC,SELECTED_PORTC_OUTPUT;
RRF _B;
GOTO SUB2;
//////////////////////////////FIN DU CYCLE D'ENVOI//////////////////////////////
SUB3:
CLRF LP0;
CLRF LP1;
CLRF LP2;
#endasm
}
} |
Thank you in advance and have a nice day ! |
|
![](templates/subSilver/images/spacer.gif) |
PrinceNai
Joined: 31 Oct 2016 Posts: 463 Location: Montenegro
|
|
Posted: Thu May 19, 2022 12:47 am |
|
|
Hi,
how are you using these functions and where are those new global variables? Your main code? |
|
![](templates/subSilver/images/spacer.gif) |
Abravius
Joined: 18 May 2022 Posts: 4
|
|
Posted: Thu May 19, 2022 1:55 am |
|
|
Hi,
There's my main code :
Code: | #include <16f1947.h>
//TRES IMPORTANT D'ACTIVER LE PLL
#fuses HS, NOPUT, NOWDT, NOBROWNOUT, PLL
#use delay (clock = 32000000)
#include "WS2812.h"
int1 Alternance;
int test, test1, test3;
void main()
{
//ACTIVATION DU PLL ET OSCILLATEUR INTERNE EN 8MGHZ PERMETTANT D'OBTENIR
setup_oscillator(OSC_PLL_ON);
output_high(PIN_C4);
Init_NeoPixel();
while(TRUE)
{
if(Alternance)
{
FillStrip(0xFF, 0, 0);
}
else
{
FillStrip(0, 0, 0xFF);
}
showStrip();
delay_ms(500);
Alternance= !Alternance;
}
} |
I've tried the "#inline" with my function into the driver, no change.
I've declared 3 new global variables at the top of the main C, it's "test1", "test2" and test3". Just with that, the speed of the PIC decreases. |
|
![](templates/subSilver/images/spacer.gif) |
Abravius
Joined: 18 May 2022 Posts: 4
|
|
Posted: Thu May 19, 2022 2:00 am |
|
|
After looking at the ".lst" file with and without global variables, I've noticed some change into my assembler code (#asm) :
Without global variable :
Code: | #asm
.................... ///////////////////////////////////////////////////////CONCERNE LA COULEUR VERTE
.................... SUB0:
.................... BTFSC LP0, 3;
01F0: BTFSC 69.3
.................... GOTO SUB1;
01F1: GOTO 1FA
.................... INCF LP0, 1;
01F2: INCF 69,F
....................
.................... BSF PORTC,SELECTED_PORTC_OUTPUT;
01F3: BSF 0E.5
01F4: NOP
.................... NOP;
.................... BTFSS _G, 0; //Condition permettant de déterminer quand la PIN doit être FALSE
01F5: BTFSS 6D.0
.................... BCF PORTC,SELECTED_PORTC_OUTPUT;
01F6: BCF 0E.5
.................... BCF PORTC,SELECTED_PORTC_OUTPUT;
01F7: BCF 0E.5
.................... RRF _G;
01F8: RRF 6D,F
.................... GOTO SUB0;
01F9: GOTO 1F0
....................
.................... ///////////////////////////////////////////////////////CONCERNE LA COULEUR ROUGE
.................... SUB1:
.................... BTFSC LP1, 3;
01FA: BTFSC 6A.3
.................... GOTO SUB2;
01FB: GOTO 204
.................... INCF LP1, 1;
01FC: INCF 6A,F
....................
.................... BSF PORTC,SELECTED_PORTC_OUTPUT;
01FD: BSF 0E.5
01FE: NOP
.................... NOP;
.................... BTFSS _R, 0; //Condition permettant de déterminer quand la PIN doit être FALSE
01FF: BTFSS 6E.0
.................... BCF PORTC,SELECTED_PORTC_OUTPUT;
0200: BCF 0E.5
.................... BCF PORTC,SELECTED_PORTC_OUTPUT;
0201: BCF 0E.5
.................... RRF _R;
0202: RRF 6E,F
.................... GOTO SUB1;
0203: GOTO 1FA
....................
.................... ////////////////////////////////////////////////////////CONCERNE LA COULEUR BLEU
.................... SUB2:
.................... BTFSC LP2, 3;
0204: BTFSC 6B.3
.................... GOTO SUB3;
0205: GOTO 20E
.................... INCF LP2, 1;
0206: INCF 6B,F
....................
.................... BSF PORTC,SELECTED_PORTC_OUTPUT;
0207: BSF 0E.5
0208: NOP
.................... NOP;
.................... BTFSS _B, 0; //Condition permettant de déterminer quand la PIN doit être FALSE
0209: BTFSS 6F.0
.................... BCF PORTC,SELECTED_PORTC_OUTPUT;
020A: BCF 0E.5
.................... BCF PORTC,SELECTED_PORTC_OUTPUT;
020B: BCF 0E.5
.................... RRF _B;
020C: RRF 6F,F
.................... GOTO SUB2;
020D: GOTO 204
....................
.................... //////////////////////////////FIN DU CYCLE D'ENVOI//////////////////////////////
.................... SUB3:
.................... CLRF LP0;
020E: CLRF 69
.................... CLRF LP1;
020F: CLRF 6A
.................... CLRF LP2;
0210: CLRF 6B
0211: MOVLB 00
.................... #endasm |
With global variables :
Code: | #asm
.................... ///////////////////////////////////////////////////////CONCERNE LA COULEUR VERTE
.................... SUB0:
.................... BTFSC LP0, 3;
00AA: MOVLB 00
00AB: BTFSC 6C.3
.................... GOTO SUB1;
00AC: GOTO 0BC
.................... INCF LP0, 1;
00AD: INCF 6C,F
....................
.................... BSF PORTC,SELECTED_PORTC_OUTPUT;
00AE: BSF 0E.5
00AF: NOP
.................... NOP;
.................... BTFSS _G, 0; //Condition permettant de déterminer quand la PIN doit être FALSE
00B0: MOVLB 01
00B1: BTFSC 20.0
.................... BCF PORTC,SELECTED_PORTC_OUTPUT;
00B2: GOTO 0B6
00B3: MOVLB 00
00B4: BCF 0E.5
00B5: MOVLB 01
.................... BCF PORTC,SELECTED_PORTC_OUTPUT;
00B6: MOVLB 00
00B7: BCF 0E.5
.................... RRF _G;
00B8: MOVLB 01
00B9: RRF 20,F
.................... GOTO SUB0;
00BA: GOTO 0AA
00BB: MOVLB 00
....................
.................... ///////////////////////////////////////////////////////CONCERNE LA COULEUR ROUGE
.................... SUB1:
.................... BTFSC LP1, 3;
00BC: BTFSC 6D.3
.................... GOTO SUB2;
00BD: GOTO 0CD
.................... INCF LP1, 1;
00BE: INCF 6D,F
....................
.................... BSF PORTC,SELECTED_PORTC_OUTPUT;
00BF: BSF 0E.5
00C0: NOP
.................... NOP;
.................... BTFSS _R, 0; //Condition permettant de déterminer quand la PIN doit être FALSE
00C1: MOVLB 01
00C2: BTFSC 21.0
.................... BCF PORTC,SELECTED_PORTC_OUTPUT;
00C3: GOTO 0C7
00C4: MOVLB 00
00C5: BCF 0E.5
00C6: MOVLB 01
.................... BCF PORTC,SELECTED_PORTC_OUTPUT;
00C7: MOVLB 00
00C8: BCF 0E.5
.................... RRF _R;
00C9: MOVLB 01
00CA: RRF 21,F
.................... GOTO SUB1;
00CB: MOVLB 00
00CC: GOTO 0BC
....................
.................... ////////////////////////////////////////////////////////CONCERNE LA COULEUR BLEU
.................... SUB2:
.................... BTFSC LP2, 3;
00CD: BTFSC 6E.3
.................... GOTO SUB3;
00CE: GOTO 0DE
.................... INCF LP2, 1;
00CF: INCF 6E,F
....................
.................... BSF PORTC,SELECTED_PORTC_OUTPUT;
00D0: BSF 0E.5
00D1: NOP
.................... NOP;
.................... BTFSS _B, 0; //Condition permettant de déterminer quand la PIN doit être FALSE
00D2: MOVLB 01
00D3: BTFSC 22.0
.................... BCF PORTC,SELECTED_PORTC_OUTPUT;
00D4: GOTO 0D8
00D5: MOVLB 00
00D6: BCF 0E.5
00D7: MOVLB 01
.................... BCF PORTC,SELECTED_PORTC_OUTPUT;
00D8: MOVLB 00
00D9: BCF 0E.5
.................... RRF _B;
00DA: MOVLB 01
00DB: RRF 22,F
.................... GOTO SUB2;
00DC: MOVLB 00
00DD: GOTO 0CD
....................
.................... //////////////////////////////FIN DU CYCLE D'ENVOI//////////////////////////////
.................... SUB3:
.................... CLRF LP0;
00DE: CLRF 6C
.................... CLRF LP1;
00DF: CLRF 6D
.................... CLRF LP2;
00E0: CLRF 6E
00E1: MOVLB 00
.................... #endasm |
I don't know why the compiler change my code . |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19358
|
|
Posted: Thu May 19, 2022 3:09 am |
|
|
What has happened is that memory by default is used from the bottom
'up'. Your new global variables are using enough bytes in the bottom
bank, that the local variables in your assembler routine have ended up
in the next bank up. Result the compiler is now having to bank switch
to access these.
Use #locate to force the global variables to be in the second bank. This
then should leave the space for the local variables in the assembler to
go back to the first bank.
If you look at the .sym file you can see where variables are placed. |
|
![](templates/subSilver/images/spacer.gif) |
Abravius
Joined: 18 May 2022 Posts: 4
|
|
Posted: Fri May 20, 2022 12:37 am |
|
|
Oh okay ! Thank you, I will try it !
For now, I've made the driver on PIC18F it's working perflectly with a frequency of 32MHz or 64MHz.
If you want it, I can send you my GitHub link. |
|
![](templates/subSilver/images/spacer.gif) |
bmete
Joined: 13 Jul 2023 Posts: 37
|
|
Posted: Wed Jul 19, 2023 1:57 am |
|
|
Hello everyone
Is it possible to operate WS2812B with PIC16F883? I dont need any sliding leds and also I dont need any high speed, I just want to turn on leds which I spesified order in the code. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19358
|
|
Posted: Wed Jul 19, 2023 3:55 am |
|
|
Yes, BUT.
The 'BUT', is because this controller needs a lot of quite accurately timed
pulses to access the LED's. This is why the author here is using a fast
clock and some parts are using assembler. The 883, is by modern standards
a slow chip, so it'll be doable, but quite hard. It is a chip designed to give
a lot of intensity levels for the LED's, not just simple ON/OFF. There are
much easier chips to drive if you only need ON/OFF.
If you want to use the 8212, I'd switch to a PIC that runs faster.
The commonest way to drive these chips is using spi, and selecting bit
patterns that give the required timing. |
|
![](templates/subSilver/images/spacer.gif) |
bmete
Joined: 13 Jul 2023 Posts: 37
|
|
Posted: Wed Jul 19, 2023 4:45 am |
|
|
Hello Ttelmah,
Unfortunatelly I already designed a PCB so I have to look an another chip which has a same package and same pin order with 16f883. I think it is pic16f18855. But its clock speed is 32MHz. What is your advice? Is 32MHz enough?
Also I operated the WS2812B module with arduino uno. After that I checked the clock speed of the Arduino uno's chip (Atmega328P). Its clock speed is 8MHz. This confused me. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19358
|
|
Posted: Wed Jul 19, 2023 6:34 am |
|
|
The PIC takes four clock cycles to execute a single instruction. The Uno,
takes one.....
The DSPIC's take only two.
Then the DSPIC's can run off (say) a 8MHz clock at 120MHz.
Etc. etc.
You need to look at the MIPS rate, not the clock rate. The UNO is normally
16MIPS, so equivalent to a PIC at 64MHz!...
Yes the 16F18855, will do it. What you do is use SPI at 4MHz,
and then send 1000 for a 0 and 1110 for a 1. Using the nibbles of a byte
just make sure the code designs the patterns needed for this before
starting the send and reloads each byte ASAP so there are no breaks.
So a 36byte array with the data all ready to send. On a PIC, minimum
clock speed to do SPI at this rate is 16MHz. Doing this has been discussed
here before, so a search should find it. Was quite a few years ago though. |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|