Förslag på PWM, ADC, I/O och DAC IC kretsar med SPI?
- Klas-Kenny
- Inlägg: 11390
- Blev medlem: 17 maj 2010, 19:06:14
- Ort: Växjö/Alvesta
Re: Förslag på PWM, ADC, I/O och DAC IC kretsar med SPI?
Stack är inte detsamma som RAM. Stacken ligger i RAM men den är inte lika stor som hela RAM:et
Re: Förslag på PWM, ADC, I/O och DAC IC kretsar med SPI?
Kan detta säga herrn något?
1.5 kb
Detta kanske förklarar varför en array på över 1500 bytes inte riktigt fungerade.
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Re: Förslag på PWM, ADC, I/O och DAC IC kretsar med SPI?
Varför skickar du med hela arrayen och inte bara en pekare?
Re: Förslag på PWM, ADC, I/O och DAC IC kretsar med SPI?
Men det är vad jag gör.
Array är ju pekare
Det ger samma krashande resultat när jag kör med detta.
Array är ju pekare
Det ger samma krashande resultat när jag kör med detta.
Kod: Markera allt
test_func(uint8_t* plot)
Re: Förslag på PWM, ADC, I/O och DAC IC kretsar med SPI?
En array är en array
En pekare är en pekare
En pekare är en pekare
Re: Förslag på PWM, ADC, I/O och DAC IC kretsar med SPI?
Det beror ju på var du deklarerat den stora arrayen. Liggen den i en funktion (utan static) så hamnar den på stacken. Deklarar du den utanför funktion eller som static hamnar den i RAM.
Skickar du in uint8_t *data eller uint8_t data[] till funktion spelar ingen roll, det blir samma sak, det blir en pekare till arrayen.
Normalt sätt undviker man lägga så stora arrayer på stack i inbyggda system, men vill du ändå göra det, kan du utöka stackens storlek i .ld filen. Dock är det lite lurigt sätta korrekt storlek för det beror på i hur många steg funktioner med mycket arrayer anropas.
Skickar du in uint8_t *data eller uint8_t data[] till funktion spelar ingen roll, det blir samma sak, det blir en pekare till arrayen.
Normalt sätt undviker man lägga så stora arrayer på stack i inbyggda system, men vill du ändå göra det, kan du utöka stackens storlek i .ld filen. Dock är det lite lurigt sätta korrekt storlek för det beror på i hur många steg funktioner med mycket arrayer anropas.
Re: Förslag på PWM, ADC, I/O och DAC IC kretsar med SPI?
Finns det inget sätt så jag kan få den ligga på FLASH? Då kanske jag måste ha den som const static? Men det vill jag inte ha.
Jag tror jag måste då offra lite av RAM. Ska testa ha en statisk uint8_t data[].
Edit:
Det fungerade inte.
Hmm...Jag får väll lösa detta på något annat sätt.
Jag tror jag måste då offra lite av RAM. Ska testa ha en statisk uint8_t data[].
Edit:
Det fungerade inte.
Hmm...Jag får väll lösa detta på något annat sätt.
Senast redigerad av DanielM 21 juni 2021, 13:44:56, redigerad totalt 1 gång.
Re: Förslag på PWM, ADC, I/O och DAC IC kretsar med SPI?
Har du många fasta värden som tex en tabell för sinus eller nåt sånt liknande bör man lägga den i flash med const, men då kan du ju inte ändra den under körning.
Ett bra sätt lösa problemet är att man har en generisk data array som alla som inkluderar den headar filen kan accessa. Då kan du åter använda samma data buffer för olika funktioner. I ena fallet kan man vill göra en lång urskrift, nästa skicka ett UDP meddelande, ta emot en fet mängd data från SPI osv.... då kan man reservera så man har en ex 2 KB buffer som funktionerna få dela på. Skulle varje funktion har en static array skulle det då behöva 8 kB istället som exempel.
Ett bra sätt lösa problemet är att man har en generisk data array som alla som inkluderar den headar filen kan accessa. Då kan du åter använda samma data buffer för olika funktioner. I ena fallet kan man vill göra en lång urskrift, nästa skicka ett UDP meddelande, ta emot en fet mängd data från SPI osv.... då kan man reservera så man har en ex 2 KB buffer som funktionerna få dela på. Skulle varje funktion har en static array skulle det då behöva 8 kB istället som exempel.
Re: Förslag på PWM, ADC, I/O och DAC IC kretsar med SPI?
Det är exakt detta jag gjorde, men det fungerade inte att skapa en stor array till att börja med.
Arrayen ska symbolisera en 2D array. Men det blir ju samma minne där med också.
Om du undrar hur koden ser ut så ser den ut så här.
Jag gör alltså en plot från en array.
Jag vet att jag kan använda memmove och jag ska göra det senare!
Arrayen ska symbolisera en 2D array. Men det blir ju samma minne där med också.
Om du undrar hur koden ser ut så ser den ut så här.
Jag gör alltså en plot från en array.
Jag vet att jag kan använda memmove och jag ska göra det senare!
Kod: Markera allt
/*
* new_values_measurement[row] Data array for inserting new values in data array for text
* new_values_plot[row] Data array for inserting new values in data array for plot
* labels[row][10] Char 2D array for displaying text labels
* 1 <= row <= 6
*/
void LCD_Show_Plot_Frame(float new_values_measurement[], uint8_t new_values_plot[], char labels[][10], uint8_t row, bool run_in_background, bool clear_plot) {
// Set rotation
ILI9341_setRotation(2);
static uint8_t plot[6*264]; // The reason why I placed it here is because stack memory is to low.
static bool firstTimeRunning = true;
// If we want to clear the plot for some reason
if(clear_plot == true || firstTimeRunning){
memset(plot, 0, 6*264); // 264 pixels from x0 to x1 for the plot. Don't change this.
firstTimeRunning = false;
}
// If we running the the plot behind the "scene"
if (run_in_background){
for (int16_t i = 51; i < 315; i++)
move(i, plot, new_values_plot, row);
return;
}
// Update the text
uint16_t colors[6] = {(uint16_t) COLOR_RED, (uint16_t) COLOR_CYAN, (uint16_t) COLOR_ORANGE, (uint16_t) COLOR_MAGENTA, (uint16_t) COLOR_GREEN3, (uint16_t) COLOR_MAROON};
uint8_t x[6] = {55, 145, 235, 55, 145, 235};
uint8_t y[6] = {10, 10, 10, 20, 20, 20};
char text_value[10];
char label[20];
for(uint8_t i = 0; i < row; i++) {
sprintf_(text_value, "%0.2f", new_values_measurement[i]);
memcpy(label, labels[i], sizeof(labels[i]));
strcat(label, text_value);
ILI9341_printText(label, x[i], y[i], colors[i], COLOR_NAVY, 1);
}
// Change
for (int16_t i = 51; i < 315; i++) {
// Clear
for(uint8_t j = 0; j < row; j++)
ILI9341_DrawPixel(i, -plot[j*264 + i - 51] + 234, COLOR_NAVY);
// Move
move(i, plot, new_values_plot, row);
// Fill
for(uint8_t j = 0; j < row; j++)
ILI9341_DrawPixel(i, -plot[j*264 + i - 51] + 234, colors[j]);
}
}
static void move(uint16_t i, uint8_t plot[], uint8_t new_values_plot[], uint8_t row) {
if (i < 314) {
// We can only move values that have a next element
for(uint8_t j = 0; j < row; j++)
plot[j*264 + i - 51] = plot[j*264 + i - 50];
} else {
// Limits so we don't write outside the box
for(uint8_t j = 0; j < row; j++)
if (new_values_plot[j] < 203)
plot[j*264 + i - 51] = new_values_plot[j];
else
plot[j*264 + i - 51] = 203;
}
}
- Klas-Kenny
- Inlägg: 11390
- Blev medlem: 17 maj 2010, 19:06:14
- Ort: Växjö/Alvesta
Re: Förslag på PWM, ADC, I/O och DAC IC kretsar med SPI?
Detta blir ju i princip en "manuell" heap, då kan man ju egentligen bara göra heap större och använda malloc istället
Re: Förslag på PWM, ADC, I/O och DAC IC kretsar med SPI?
Nja du kan inte fragmentera den på samma sätt på heap, vilket man vill undvika i inbyggda system så malloc ex. kan ge fel efter 1000 timmars körning om man fragmenterat den. Det är fortfarande statiskt minne (under förusättning att man inte fragmenterar det själv då)Detta blir ju i princip en "manuell" heap, då kan man ju egentligen bara göra heap större och använda malloc istället
Re: Förslag på PWM, ADC, I/O och DAC IC kretsar med SPI?
Att utöka stacken tror jag ska låta bli. Jag har ingen erfarenhet om detta.Rick81 skrev: ↑21 juni 2021, 09:16:57 Normalt sätt undviker man lägga så stora arrayer på stack i inbyggda system, men vill du ändå göra det, kan du utöka stackens storlek i .ld filen. Dock är det lite lurigt sätta korrekt storlek för det beror på i hur många steg funktioner med mycket arrayer anropas.
Jag har testat lagt den på RAM .bss och plot är 1.55 kB.
Edit:
Nu vet jag vad som också orsakar, trots att plot är statisk.
Denna orsakar också! Jag försöker alltså att rensa plot först.
Kod: Markera allt
memset(plot, 0, sizeof(plot));
Kod: Markera allt
for(uint16_t i = 0; i < sizeof(plot); i++)
plot[i] = 0;
Kod: Markera allt
for(uint8_t i = 0; i < 6; i++)
memset(plot[i], 0, sizeof(plot[i]));
Re: Förslag på PWM, ADC, I/O och DAC IC kretsar med SPI?
Testa om detta funkar:
Kod: Markera allt
uint8_t plot[6][264];
int main()
{
memset(plot, 0, sizeof(plot));
Re: Förslag på PWM, ADC, I/O och DAC IC kretsar med SPI?
Alltså i main fungerar allt. Det är bara när funktionen är i en annan .c fil.
Men jag tror jag ska undvika skapa stora arrayer.
Målet var att skriva ut en plot på min LCD igenom att flytta pixlar. Det fungerar bra om det går långsamt, sämre om det går snabbt.
Men jag har bestämt mig att bara skriva ut värderna som min STM32 visar.
Det går riktigt bra nu Jag har fått SDADC, signel och differentiell att fungera. Dock så visar dom rätt höga värden, men jag tror detta har med att dom är förskjutna.
Målet med allt är att det ska vara en liten STM32 PLC som kan logga, styra och mäta Fri källkod också.
Exempel:
Vid singel SDADC så får jag 33490 om jag har 0 volt in. Annars blir det 12453 om jag applicerar 3.3v på ingången. Ungefär.
Vid differentiell SDADC så får jag 65509 om jag har 0 volt i skillnad. Applicerar jag 3.3 volt på någon av ingången så får jag ca 32523.
Jag har för mig att när jag konverterade om dessa uint16_t värden till int16 i Java, så fick jag 0 till 16-bit helt perfekt.
Edit:
En fråga! Är detta ett smart val?
Låt oss säga att jag har en encoder som har räkningen mellan 0x00 till 0xFFFF.
Men jag vill även bestämma åt vilket håll encodern roterar. Är det smart då och säga att encodern har räkningen mellan 0x00 till 0x7fff där sista biten är antingen en 1 eller 0 beroende på rotation?
0x7fff är alltså 15-bit.
Låt säga att 1 är för rotation medsols.
Då får jag värden mellan 32768 och 65535.
Om den roterar motsols så får jag värden mellan 0 till 32767.
Typ så här.
Men jag tror jag ska undvika skapa stora arrayer.
Målet var att skriva ut en plot på min LCD igenom att flytta pixlar. Det fungerar bra om det går långsamt, sämre om det går snabbt.
Men jag har bestämt mig att bara skriva ut värderna som min STM32 visar.
Det går riktigt bra nu Jag har fått SDADC, signel och differentiell att fungera. Dock så visar dom rätt höga värden, men jag tror detta har med att dom är förskjutna.
Målet med allt är att det ska vara en liten STM32 PLC som kan logga, styra och mäta Fri källkod också.
Exempel:
Vid singel SDADC så får jag 33490 om jag har 0 volt in. Annars blir det 12453 om jag applicerar 3.3v på ingången. Ungefär.
Vid differentiell SDADC så får jag 65509 om jag har 0 volt i skillnad. Applicerar jag 3.3 volt på någon av ingången så får jag ca 32523.
Jag har för mig att när jag konverterade om dessa uint16_t värden till int16 i Java, så fick jag 0 till 16-bit helt perfekt.
Edit:
En fråga! Är detta ett smart val?
Låt oss säga att jag har en encoder som har räkningen mellan 0x00 till 0xFFFF.
Men jag vill även bestämma åt vilket håll encodern roterar. Är det smart då och säga att encodern har räkningen mellan 0x00 till 0x7fff där sista biten är antingen en 1 eller 0 beroende på rotation?
0x7fff är alltså 15-bit.
Låt säga att 1 är för rotation medsols.
Då får jag värden mellan 32768 och 65535.
Om den roterar motsols så får jag värden mellan 0 till 32767.
Typ så här.
Kod: Markera allt
static uint16_t encoder0_difference;
static uint16_t encoder1_difference;
static TIM_HandleTypeDef* encoder0_tim;
static TIM_HandleTypeDef* encoder1_tim;
uint16_t compare(uint16_t count, uint16_t difference);
void STM32_PLC_Start_Encoder(TIM_HandleTypeDef* htim4, TIM_HandleTypeDef* htim19) {
HAL_TIM_Encoder_Start_IT(htim4, TIM_CHANNEL_1);
HAL_TIM_Encoder_Start_IT(htim4, TIM_CHANNEL_2);
HAL_TIM_Encoder_Start_IT(htim19, TIM_CHANNEL_1);
HAL_TIM_Encoder_Start_IT(htim19, TIM_CHANNEL_2);
encoder0_tim = htim4;
encoder1_tim = htim19;
}
uint16_t STM32_PLC_Encoder0() {
uint16_t encoder0_count = encoder0_tim->Instance->CNT;
encoder0_difference = compare(encoder0_count, encoder0_difference);
bool encoder0_direction = !(__HAL_TIM_IS_TIM_COUNTING_DOWN(encoder0_tim));
/* Values between 0 and 0xFFFF */
if(encoder0_direction)
return 0x8000 + encoder0_difference; /* Positive rotation: 0x8000 - 0xFFFF */
else
return 0x7FFF - encoder0_difference; /* Negative rotation: 0 - 0x7FFF */
}
uint16_t STM32_PLC_Encoder1() {
uint16_t encoder1_count = encoder1_tim->Instance->CNT;
encoder1_difference = compare(encoder1_count, encoder1_difference);
bool encoder1_direction = !(__HAL_TIM_IS_TIM_COUNTING_DOWN(encoder1_tim));
/* Values between 0 and 0xFFFF */
if(encoder1_direction)
return 0x8000 + encoder1_difference; /* Positive rotation: 0x8000 - 0xFFFF */
else
return 0x7FFF - encoder1_difference; /* Negative rotation: 0 - 0x7FFF */
}
void STM32_PLC_Encoder0_Set_Prescaler(uint16_t prescaler) {
encoder0_tim->Instance->PSC = prescaler;
}
void STM32_PLC_Encoder1_Set_Prescaler(uint16_t prescaler) {
encoder1_tim->Instance->PSC = prescaler;
}
uint16_t STM32_PLC_Encoder_Get(uint8_t i) {
switch(i){
case 0:
return STM32_PLC_Encoder0();
case 1:
return STM32_PLC_Encoder1();
default:
return 0x7FFF; /* No rotation */
}
}
uint16_t compare(uint16_t count, uint16_t difference) {
if(count > difference)
return count - difference;
else if (count < difference)
return difference - count;
else
return 0;
}