hallo,
ik ben wat berekeningen in C aan het doen. nu kom ik er achter dat 0/1000 niet 0 is (wat je wel zou verwachten).
klopt dat ? en hoe doe je dat dan wel ?
tnx.
Golden Member
hallo,
ik ben wat berekeningen in C aan het doen. nu kom ik er achter dat 0/1000 niet 0 is (wat je wel zou verwachten).
klopt dat ? en hoe doe je dat dan wel ?
tnx.
Special Member
Moeilijk wat zinnigs te zeggen zonder code...
Er zou wel degelijk 0 uit een integer deling moeten komen...
Zie Paulinha_B
Je bent toch niet met floats aan het stoeien? Dan wordt het
0.0/1000.0
Het overkomt me wel eens dat ik .0 moet toevoegen om float te forceren.
Verder sluit ik me (alweer ) helemaal aan bij @Arco. Toon eens de code, en de output? En misschien kun je het ruimere plaatje schetsen: wat dient er bereikt te worden?
Golden Member
het is een for loop:
c code:
for (Y_scan = 0; Y_scan < 37000; Y_scan = Y_scan + 1000)
verder op doe ik dan:
c code:
LTOY = (Y_scan / 1000) + 3;
vul ik i.p.v. Y_scan gewoon een 0 in, dan gaat het wel goed (LTOY =3)
edit: Y_scan is gedeclareerd als een long.
Special Member
Waarde van LTOY zou dus tussen de 3 en 40 moeten liggen.
Het zijn wel allemaal gewoon unsigned integer variabelen?
Edit: Waarom een long als je alleen positieve waardes gebruikt?
[Bericht gewijzigd door Arco op 30 mei 2020 11:58:29 (23%)
Tegenwoordig heb je handige online C compilers om dit soort dingetjes snel te kunnen testen.
https://onlinegdb.com/HkEQ0ikhI
LTOY = '39'
Persoonlijk houd ik liever de STDINT aan, dus uint32_t ect. Dat is altijd duidelijk en processor onafhankelijk.
Golden Member
ik heb een int geprobeerd, maar toen kon ik niet 37000 gebruiken maar wel b.v. 32000. daar trok ik de conclusie uit dat de int "signed" was, en ben over gestapt naar de "long".
edit: wat hardass zegt vind ik ook duidelijker, maar ik weet te weinig v/d materie en dus ook niet of ik dat ongestraft kan toepassen.
[Bericht gewijzigd door trix op 30 mei 2020 12:03:47 (28%)
Special Member
Compilers die ik gebruik hebben words voor 2 bytes en dwords voor 4 bytes unsigned...
Een signed 16 bit int gaat tot +/- 32767, een unsigned 16 bit int tot 65535
Een int is in 'C' standaard een signed getal. Je moet expliciet 'unsigned int' declareren. Die long zal ook signed zijn.\
Maar dan nog, 0/N zal toch altijd 0 op moeten leveren, tenzij je floats gebruikt.
[Bericht gewijzigd door flipflop op 30 mei 2020 12:23:14 (26%)
Special Member
Zou er ergens een instelling zijn dat delingen altijd als float gedaan worden? Maar dan nog, LTOY is een int (of long), dus zou alsnog omgezet moeten worden...
c code:
Unsigned int LTOY, Y_scan;
LTOY = (Y_scan / 1000UL) + 3;
Wat krijg je er eigenlijk wel uit, als het geen 0 is?
nul gedeeld door 1000 is gewoon nul. Dat is in C ook gewoon zo.
Ik heb een testprogramma geschreven:
code:
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char **argv)
{
int a, b;
a = 0;
b = 1000;
if (argc > 1) a = atoi (argv[1]);
if (argc > 2) a = atoi (argv[2]);
printf ("%d / %d = %d. \n", a, b, a/b);
}
en dat geeft gewoon het verwachte resultaat:
code:
% ./a.out
0 / 1000 = 0.
%
Update net even je LTOY code toegevoegd...
code:
void test_trix (void)
{
int Y_scan, LTOY;
for (Y_scan = 0; Y_scan < 37000; Y_scan = Y_scan + 1000) {
LTOY = (Y_scan / 1000) + 3;
printf ("Y_scan = %d, LTOY = %d.\n", Y_scan, LTOY);
}
}
En ook dat werkt conform verwachting.(begint bij 0 / 3 en eindigt met 36000 / 39 als laatste.)
Golden Member
Wat krijg je er eigenlijk wel uit, als het geen 0 is?
41
[Bericht gewijzigd door trix op 30 mei 2020 14:24:05 (31%)
Golden Member
ik post even een grotere stuk code. wellicht is het dan wat duidelijker, en mischien zien julie nog andere gekke dingen.
c code:
int X_scan = 0;
long Y_scan = 0;
int Y_bit = 0;
int RAM_address = 0;
int check_byte_1 = 0; // checked byte
int check_byte_2 = 0; // byte right check
int check_byte_3 = 0; // byte below check
int check_byte_4 = 0; // corner bit check
int LTOX = 0; // Left Top Out Y pos
int LTOY = 0; // Left Top Out Y pos
int LTO_found = 0; // we found the Left Top Out corner
int RTOX = 0; // Right Top Out Y pos
int RTOY = 0; // Right Top Out Y pos
int RTO_found = 0; // we found the right Top Out corner
int tester1 = 0; // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
int tester2 = 0; // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
int tester3 = 0; // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
int control_is_ending = 0; // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
int xx = 1; // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
int yy = 1; // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
int zz = 1; // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR1)|(1<<SPR0); // Enable SPI, Master, set clock rate fck/128
uint8_t SPI_transfer(uint8_t data) // functie
{
SPDR = data;
while(!(SPSR & (1<<SPIF))); // Wait for transmission complete
return SPDR;
}
uint32_t address;
PORTA |= (1 << PINA0); // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
for (Y_scan = 0; Y_scan < 37000; Y_scan = Y_scan + 1000)
{
for (X_scan = 0; X_scan < 300; X_scan ++)
{
// RAM_address = Y_scan + X_scan + 1;
RAM_address = X_scan + 1;
PORTG &= ~(1 << PING5); // make SS ext. RAM pin = 0
SPI_transfer(0b00000011); // read data from memory
address = RAM_address; // is address in ext. RAM
SPI_transfer((address>>16)); // address
SPI_transfer((address>>8)); // address
SPI_transfer((address)); // address
SPI_transfer(0x00); // dummy when you want to read a byte from ext. RAM
PORTG |= (1 << PING5); // make SS ext. RAM pin = 1
check_byte_1 = SPDR; // 76543210
// below: if 2 neighbors bits are "1", check the next byte
if ((check_byte_1 == 192) || (check_byte_1 == 224) || (check_byte_1 == 240) || (check_byte_1 == 248) ||
(check_byte_1 == 252) || (check_byte_1 == 254) || (check_byte_1 == 255))
{
PORTG &= ~(1 << PING5); // make SS ext. RAM pin = 0
SPI_transfer(0b00000011); // read data from memory
address = RAM_address + 1; // is address in ext. RAM from the byte right to the checked byte
SPI_transfer((address>>16)); // address
SPI_transfer((address>>8)); // address
SPI_transfer((address)); // address
SPI_transfer(0x00); // dummy when you want to read a byte from ext. RAM
PORTG |= (1 << PING5); // make SS ext. RAM pin = 1
check_byte_2 = SPDR; // 76543210
// below: if in the next byte also the same 2 neighbors bits are "1"
if ((check_byte_1 == 192) && (check_byte_2 == 192)) { LTOY = (Y_scan / 1000) + 7; }
if ((check_byte_1 == 224) && (check_byte_2 == 224)) { LTOY = (Y_scan / 1000) + 6; }
if ((check_byte_1 == 240) && (check_byte_2 == 240)) { LTOY = (Y_scan / 1000) + 5; }
if ((check_byte_1 == 248) && (check_byte_2 == 248)) { LTOY = (Y_scan / 1000) + 4; }
if ((check_byte_1 == 252) && (check_byte_2 == 252)) { LTOY = (Y_scan / 1000) + 3; }
if ((check_byte_1 == 254) && (check_byte_2 == 254)) { LTOY = (Y_scan / 1000) + 2; }
if ((check_byte_1 == 255) && (check_byte_2 == 255)) { LTOY = (Y_scan / 1000) + 1; }
if (LTO_found == 0) { LTOX = RAM_address; LTO_found = 1; }
// below: if bit #7 = "1"
if ((check_byte_1 == 128) && (check_byte_2 == 128))
{
PORTG &= ~(1 << PING5); // make SS ext. RAM pin = 0
SPI_transfer(0b00000011); // read data from memory
address = RAM_address + 1000; // is address in ext. RAM from the byte below the checked byte
SPI_transfer((address>>16)); // address
SPI_transfer((address>>8)); // address
SPI_transfer((address)); // address
SPI_transfer(0x00); // dummy when you want to read a byte from ext. RAM
PORTG |= (1 << PING5); // make SS ext. RAM pin = 1
check_byte_3 = SPDR; // 76543210
// below: now we gonna check for the corner bit
if (check_byte_3 == 1)
{
PORTG &= ~(1 << PING5); // make SS ext. RAM pin = 0
SPI_transfer(0b00000011); // read data from memory
address = RAM_address + 1001; // is address in ext. RAM from the "corner byte"
SPI_transfer((address>>16)); // address
SPI_transfer((address>>8)); // address
SPI_transfer((address)); // address
SPI_transfer(0x00); // dummy when you want to read a byte from ext. RAM
PORTG |= (1 << PING5); // make SS ext. RAM pin = 1
check_byte_4 = SPDR; // 76543210
if ((check_byte_4 == 1) && (LTO_found == 0))
{
LTOX = X_scan; LTO_found = 1;
}
}
}
} // from: if ((check_byte_1 == 3.....................
// *****************************************************************************************************
// *** NOW WE FOUND THE LTO CORNER, WE GONNA SEARCH FOR THE RTO CORNER *********************************
// *****************************************************************************************************
if ((check_byte_1 == 0) && (LTO_found == 1) && (RTO_found == 0)) // this is the end of the window
{
RTOX = RAM_address;
RTOY = LTOY;
RTO_found = 1;
}
// *****************************************************************************************************
// *** NOW WE FOUND THE RTO CORNER, WE GONNA SEARCH FOR THE LTI_1 CORNER ********************************
// *****************************************************************************************************
} // from: (for (X_scan..............
} // from: (for (Y_scan..............
PORTA |= (1 << PINA4); // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
control_is_ending = 1;
#include "check_the_corner_bytes.h"
LTOY is altijd nul, de variabele krijgt nooit een nieuwe waarde toegekend. Ik snap niet wat dat met delen te maken heeft.
Golden Member
jawel, in het stukje:
c code:
if ((check_byte_1 == 192) && (check_byte_2 == 192)) { LTOY = (Y_scan / 1000) + 7; }
if ((check_byte_1 == 224) && (check_byte_2 == 224)) { LTOY = (Y_scan / 1000) + 6; }
if ((check_byte_1 == 240) && (check_byte_2 == 240)) { LTOY = (Y_scan / 1000) + 5; }
if ((check_byte_1 == 248) && (check_byte_2 == 248)) { LTOY = (Y_scan / 1000) + 4; }
if ((check_byte_1 == 252) && (check_byte_2 == 252)) { LTOY = (Y_scan / 1000) + 3; }
if ((check_byte_1 == 254) && (check_byte_2 == 254)) { LTOY = (Y_scan / 1000) + 2; }
if ((check_byte_1 == 255) && (check_byte_2 == 255)) { LTOY = (Y_scan / 1000) + 1;
Ja sorry. Ik was te snel.
In het kader van "misschien zien jullie nog wat"....
code:
PORTG &= ~(1 << PING5); // make SS ext. RAM pin = 0
SPI_transfer(0b00000011); // read data from memory
address = RAM_address + 1; // is address in ext. RAM from the byte right to the checked byte
SPI_transfer((address>>16)); // address
SPI_transfer((address>>8)); // address
SPI_transfer((address)); // address
SPI_transfer(0x00); // dummy when you want to read a byte from ext. RAM
PORTG |= (1 << PING5); // make SS ext. RAM pin = 1
check_byte_2 = SPDR; // 76543210
is volgens mij het lezen van een byte uit een externe RAM.
Maak daar een functie van:
code:
check_byte_2 = ram_read (RAM_address+1);
Dat maakt de code overzichtelijker omdat je in dit deel van de code niet bezig bent met "SPI hardware aansturen" maar gewoon met bytes uit ram halen.
Ohh... Ik zie dezelfde code nu al 3x terugkomen. De "interessante" code wordt daarmee zo al direct 33 regels korter en dus makkelijker te bevatten voor mensen.
Dan kan je zeggen dat het minder efficient is. Maar werkende code is VEEL belangrijker dan efficiente code. Mocht je echt denken dat het veel uitmaakt dat die code inline is dan kan je de compiler vragen om dat inderdaad te doen.
Op een CPU met een instructie cache (alles groter dan een AVR) is het trouwens al snel verstandig om WEL functies te gebruiken in zo'n geval als hier: nu gebruik je 3x zo veel I-cache als wanneer je een functie zou aanroepen. En omdat de cache niet onbeperkt is, loont het om je cache-footprint kleiner te houden. En zeker omdat je hier IO met externe dingen doet, zal het toch veel trager zijn dan dat de CPU kan. Dus ZEKER een reden om het in een functie te doen.
Dan nog een dingetje:
code:
#define RAM_CS_PORT PORTG
#define RAM_CS_PIN PING5
#define ACTIVATE_RAM_CS() RAM_CS_PORT &= ~_BV(RAM_CS_PIN)
#define DEACTIVATE_RAM_CS() RAM_CS_PORT |= _BV(RAM_CS_PIN)
uint8_t read_ram(long addr) // Die long hier betekent dat je al een paar bugs gevonden hebt in je code!
{
uint8_t v;
ACTIVATE_RAM_CS();
SPI_transfer(0b00000011);
SPI_transfer(addr>>16); // address
SPI_transfer(addr>8); // address
SPI_transfer(addr); // address
v = SPI_transfer(0); // send dummy zero, chip returns data;
DEACTIVATE_RAM_CS();
return v;
}
Het lezen van het SPIDR nadat je de transfer hebt afgerond vind ik "vaag". Je gebruikt een SPI_transfer functie, die moet dan ook maar de ontvangen data teruggeven. de implementatie code die ik op het web vond doet dat ook inderdaad.
[Bericht gewijzigd door rew op 30 mei 2020 16:03:32 (45%)
Golden Member
inderdaat het lezen van een byte uit de ext. RAM
klopt, daar ben ik al mee bezig geweest. maar kreeg dat niet zo snel voor mekaar, en de prioriteiten lagen anders.
probleem was een beetje dat er in dat stukje wat je post al een functie zit nl.: SPI_transfer.
Wat is er? Denk je dat je in een functie niet nog een functie kan aanroepen? Dat is jaren zestig computer-kunde. Dat kan dus ondertussen al meer dan vijftig jaar.
Golden Member
dat van het delen: LTOY/1000 is opgelost.
probleem was dat ik LTOY niet een malig schreef, maar iedere keer als de "loop" weer langs kwam.
stukje code veranderd:
c code:
if (LTO_found == 0)
{
LTO_found = 1;
LTOX = RAM_address;
if ((check_byte_1 == 192) && (check_byte_2 == 192)) { LTOY = (Y_scan / 1000) + 7; }
if ((check_byte_1 == 224) && (check_byte_2 == 224)) { LTOY = (Y_scan / 1000) + 6; }
if ((check_byte_1 == 240) && (check_byte_2 == 240)) { LTOY = (Y_scan / 1000) + 5; }
if ((check_byte_1 == 248) && (check_byte_2 == 248)) { LTOY = (Y_scan / 1000) + 4; }
if ((check_byte_1 == 252) && (check_byte_2 == 252)) { LTOY = (Y_scan / 1000) + 3; }
if ((check_byte_1 == 254) && (check_byte_2 == 254)) { LTOY = (Y_scan / 1000) + 2; }
if ((check_byte_1 == 255) && (check_byte_2 == 255)) { LTOY = (Y_scan / 1000) + 1; }
}
Golden Member
ik zou inderdaad zoals rew al terecht zegt gebruik willen maken van een functie.
ik maak hier over een nieuwe topic aan.
Als 0/N 41 oplevert, dan weet je onmiddellijk dat je zelf iets fout doet. Dan kan geen fout vd compiler meer zijn. Dan zou het bv 0.00000000019 of zo moeten opleveren (al kan dat niet met een long natuurlijk).
Ik heb je vraag al beantwoord voordat je hem gesteld hebt.