AVR C - sträng hoppar in i annan, utan anledning!

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
toffie
Inlägg: 1888
Blev medlem: 22 juli 2004, 21:38:07
Ort: Töreboda / Stockholm
Kontakt:

AVR C - sträng hoppar in i annan, utan anledning!

Inlägg av toffie »

Hej på er,
Sitter och håller på med tester av AES kryptering, som jag skrivit om för någon dag sedan.

Men helt plötsligt så får jag ett jättekonstigt fel.. En sträng lägger sig automatiskt efter en annan, utan att jag bett om det.. Svårt att förklara, men se följande så kanske ni förstår.

Kod: Markera allt

Sträng som jag vill skicka över UART till datorn;
0x41, 0x42, 0x43, 0x44, 0x40, 0x30, 0x31, 0x32

Sträng som tas emot på datorn;
0x41, 0x42, 0x43, 0x44, 0x40, 0x30, 0x31, 0x32, 0x4B, 0xFA, 0x1A, 0xBB, 0xC9, 0x87, 0x51, 0x83, 0x6D, 0x2A, 0x98, 0xDC, 0x98, 0xC1, 0xBE, 0xB5

Strängen som läggs på kommer från en annan uint8_t variabel.
Koden är som följer;

Kod: Markera allt

uint8_t AESkey[]  = {	0x4B, 0xFA, 0x1A, 0xBB,
						0xC9, 0x87, 0x51, 0x83,
						0x6D, 0x2A, 0x98, 0xDC,
						0x98, 0xC1, 0xBE, 0xB5 };

uint8_t AESdataENC[] = {	0x41, 0x42, 0x43, 0x44,
						0x40, 0x30, 0x31, 0x32 };
DÄREMOT! märkte jag efter en stund att om jag flyttar AESkey array/sträng/uint8_t/variabeln.. vad de nu kallas, så den ligger under AESdataENC delen, då händer det inte..

Det jag då förmodar är att AESkey är öppen/oavslutad, men inte vad jag kan se.. Kan ni se det? Sen borde jag ha fått ett kompiler fel i AtmelStudio, men det får jag inte heller.

Så varför fungerar följande, men inte det ovan??? - Dvs.. Jag får endast AESdataENC variabeln överskickad på UART'en med följande ordning på variablerna.

Kod: Markera allt

uint8_t AESdataENC[] = {	0x41, 0x42, 0x43, 0x44,
						0x40, 0x30, 0x31, 0x32 };

uint8_t AESkey[]  = {	0x4B, 0xFA, 0x1A, 0xBB,
						0xC9, 0x87, 0x51, 0x83,
						0x6D, 0x2A, 0x98, 0xDC,
						0x98, 0xC1, 0xBE, 0xB5 };
Nerre
Inlägg: 27229
Blev medlem: 19 maj 2008, 07:51:04
Ort: Upplands väsby

Re: AVR C - sträng hoppar in i annan, utan anledning!

Inlägg av Nerre »

Spontan gissning utan att ha kollat på koden:

En sträng i C skall avslutas med ett NULL-tecken (0x00). Det innebär att om strängen ska kunna rumma 10 "relevanta" tecken så måste den vara 11 tecken lång för att få plats med ett NULL på slutet.

Att glömma att reservera palts för NULL ligger antagligen på många topp-listor över vanligaste missarna i C.
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 46974
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: AVR C - sträng hoppar in i annan, utan anledning!

Inlägg av TomasL »

du kan ju börja med att posta koden som skickar strängen.
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 46974
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: AVR C - sträng hoppar in i annan, utan anledning!

Inlägg av TomasL »

Nerre skrev:Spontan gissning utan att ha kollat på koden:

En sträng i C skall avslutas med ett NULL-tecken (0x00). Det innebär att om strängen ska kunna rumma 10 "relevanta" tecken så måste den vara 11 tecken lång för att få plats med ett NULL på slutet.

Att glömma att reservera palts för NULL ligger antagligen på många topp-listor över vanligaste missarna i C.
Det gäller bara textsträngar som skall hanteras av de "inbyggda strängfunktionerna".
Detta tolkar jag som vanliga arrays.
bearing
Inlägg: 11676
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Re: AVR C - sträng hoppar in i annan, utan anledning!

Inlägg av bearing »

Vad är kommandot för att skicka strängen?
Anges någon längd på strängen i det kommandot?

Många funktioner förutsätter nollterminerade strängar, för att på så sätt slippa ta längden som argument. De funktionerna är till för att sända text.

För att skicka data kanske det inte finns någon färdig funktion, utan du kanske själv behöver skriva en som anropar "send_byte" funktionen i en loop som går igenom arrayen.
Användarvisningsbild
AndLi
Inlägg: 18277
Blev medlem: 11 februari 2004, 18:17:59
Ort: Knivsta
Kontakt:

Re: AVR C - sträng hoppar in i annan, utan anledning!

Inlägg av AndLi »

Prova nedanstående så ska du se att det funkar!

Kod: Markera allt

uint8_t AESdataENC[] = {   0x41, 0x42, 0x43, 0x44,
                  0x40, 0x30, 0x31, 0x32,0x00 };

Varför inte skriva uint8_t AESdataENC[] = "ABCD123" ; istället, tydligare vad du stoppar in då, och då får du din nullterminering automagiskt
Användarvisningsbild
bit96
Inlägg: 2529
Blev medlem: 3 september 2007, 10:04:29
Ort: Säffle

Re: AVR C - sträng hoppar in i annan, utan anledning!

Inlägg av bit96 »

Du skriver om strängar men har formellt skapat fält.
En sträng MÅSTE avslutas med noll-tecknet.

Dina två fält lagras troligen i följd i minnet, utan nolltecken vare sig emellan eller efter sista fältet.

Använder man citationstecken när man gör strängar lägger C-kompilatorn automatiskt till ett nolltecken.

Kod: Markera allt

char text="abcde"
skapar ett fält med 6 tecken, den fem tecknen abcde samt ett nolltecken.

Kod: Markera allt

 char text={'a', 'b', 'c', 'd', 'e'};
skapar ett fält med 5 tecken, de fem bokstäverna abcde.


Lösning:

Kod: Markera allt

uint8_t AESdataENC[] = {   0x41, 0x42, 0x43, 0x44,
                  0x40, 0x30, 0x31, 0x32, 0x00 };
Edit: 2:a på bollen. :)
Användarvisningsbild
toffie
Inlägg: 1888
Blev medlem: 22 juli 2004, 21:38:07
Ort: Töreboda / Stockholm
Kontakt:

Re: AVR C - sträng hoppar in i annan, utan anledning!

Inlägg av toffie »

WOW! Seriöst, wow.. Vad ni svarar.. så många och så snabbt! TACK! :D

Oj, ska försöka svara på allt..


Nerre
Att lägga in NULL i slutet på strängen, löste problemet och vidare löste det ytterligare problem jag hade som jag tänkte ta efter jag löst det problemet jag skrev om i tråden :D Det här är något jag aldrig läst om ens en gång, inte för att jag studerat C överdrivet mycket.. det är endast på hobbybasis min kunskap ligger - jag lär mig längs med vägen, som nu ;) :D

TomasL
Koden som skickar strängen är så enkel som följande;

Kod: Markera allt

#include <avr/io.h>
#include <util/delay.h>
#include <inttypes.h>
#include <avr/interrupt.h>
#include <stdlib.h>

#ifndef F_CPU
#define F_CPU 8000000UL
#endif

#define USART_BAUD_RATE				1200	// Bits Per Second

#define USART_RX_BUFFER_SIZE		32		// n Bytes in Receive buffer
#define USART_TX_BUFFER_SIZE		32		// n Bytes in Transmit buffer

uint8_t AESkey[]  = {		0x4B, 0xFA, 0x1A, 0xBB,
							0xC9, 0x87, 0x51, 0x83,
							0x6D, 0x2A, 0x98, 0xDC,
							0x98, 0xC1, 0xBE, 0xB5 };

uint8_t AESdataENC[] = {	0x41, 0x42, 0x43, 0x44,
							0x40, 0x31, 0x32, 0x33 };

int main(void)
{
	USART_INIT();
	_delay_ms(10);
	
	
	USART_SEND(AESdataENC);
	while (1)
	{
		//loop
	}
}


void USART_INIT(void)
{
	UBRRH = UBRRH_VALUE;
	UBRRL = UBRRL_VALUE;
	
	UCSRA = 0x00;
	UCSRB |= (1 << RXEN); // RXEN, Enable RX
	UCSRB |= (1 << RXCIE); // RXCIE, Enable RX interrupt
	UCSRB |= (1 << TXEN); // TXEN, Enable TX
	UCSRC = 0x86; // 8 Data, 1 Stop, No Parity
}

void USART_SEND(const char *s)
{
	// Go through all characters sent into the send-function
	while (*s)
	
	// Send characters off to the USART bus, one by one
	USART_SEND_BYTE(*s++);
}

void USART_SEND_BYTE(char data)
{
	// Wait if a byte is being transmitted
	loop_until_bit_is_set(UCSRA, UDRE);

	// Send the given data
	UDR = data;
}
Koden i övrigt fungerar utan problem, jag kan skicka data över UART'en om jag bara kommenterar bort AESkey strängen.

Koden ovan reflekterar INTE Nerre's förslag med ett NULL tecken i slutet. Följande är en uppdatering och var det som gjorde att det nu fungerar!

Kod: Markera allt

uint8_t AESkey[]  = {		0x4B, 0xFA, 0x1A, 0xBB,
							0xC9, 0x87, 0x51, 0x83,
							0x6D, 0x2A, 0x98, 0xDC,
							0x98, 0xC1, 0xBE, 0xB5, 0x00 };

uint8_t AESdataENC[] = {	0x41, 0x42, 0x43, 0x44,
							0x40, 0x31, 0x32, 0x33, 0x00 };
bearing
Kommando/kod enligt ovan, ingen angiven längd på det som ska skickas.. bara skicka! Funktionen "send_byte" som du nämner har jag skapat sedan länge, så den fanns redan ;) Inte för att vara märkvärdig eller något, men det var bland det första jag "lyckades" skriva och det fungerade :D

AndLi
Enligt rekommendation av Nerre, alltså likadant som ditt förslag, det fungerade perfekt! :)

Anledningen till att jag inte skriver i ren ASCII är för att när jag felsöker med att skicka över bland annat den sträng som kommer ut från AES krypteringen så innehåller den tecken som inte visas alls eller visas korrekt i terminalfönstret. Sen har jag ett hex baserat protokoll för kommunikationen, så det blir mest enklast i mitt läge :)

bit96
Underbart! Många tack för beskrivningen! Tillsammans med ditt inlägg och Nerre's info om NULL tecknet i slutet på strängen, eller tydligen fältet då :P så förstod jag vad det var som strulade och framförallt!! VARFÖR! Det är ett sånt här svar som får en att hoppa en bakåtvolt och jubla - jag har lärt mig något, som förmodligen kommer sitta i :D


Än en gång, TACK alla! Uppskattar verkligen er hjälp och tid i detta!
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 46974
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: AVR C - sträng hoppar in i annan, utan anledning!

Inlägg av TomasL »

din USART_SEND vill uppenbarligen ha strängar, annars hade det funnits ett argument med hur många byte som skall skickas.
bearing
Inlägg: 11676
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Re: AVR C - sträng hoppar in i annan, utan anledning!

Inlägg av bearing »

Med tanke på att du skrivit strängen i hex. Är det mening att du ska kunna skicka allmän data, eller ska det vara text?

För om den allmänna datan innehåller 0 någonstans kommer ju överföringen stanna.
Användarvisningsbild
toffie
Inlägg: 1888
Blev medlem: 22 juli 2004, 21:38:07
Ort: Töreboda / Stockholm
Kontakt:

Re: AVR C - sträng hoppar in i annan, utan anledning!

Inlägg av toffie »

Måste säga, TACK allihop igen.. jag är så fascinerad över att det hela fungerar, med kryptering och nu över de här billiga trådlösa 433mhz modulerna.. TACK! :D

TomasL
Jo det är så jag skrivit funktionen för något år sen, använder samma av enkelhetens skull.. Det "hjälper" mig då jag inte vet hur många tecken jag vill skicka, då det skiljer sig från gång till gång, projekt till projekt. Den funktionen har "alltid" fungerat, så jag kör på den till jag är tvungen att köra med en annan - dvs, att jag lär mig vidare hur man kan/ska göra.

I detta läge hade jag förmodligen missat NULL tecknet om jag angett exakt hur många byte som skulle skickas. Det känns som om jag lärt mig något viktigare med att vara tvungen att ange NULL tecknet, då begränsning av antal bytes som ska skickas känns som ett "fulhack".

Inte för att själva idén är dum som du har, men tror du inte att lösningen med att använda ett NULL tecken är bättre i detta fall? :)


bearing
Oj.. här kom istället ett möjligt bakslag.. Just för detta fall så ska jag inte ha några 0 / 0x00 värden. Inte medvetet.. Huruvida AES krypteringen skapar ett 0x00 eller liknande har jag ju förstås ingen aning om.

Men du menar att om jag skickar 0x00 i datatrafiken så kommer AES dekrypteringen tro att det är slutet på det krypterade "paketet", även om det kanske inte är fallet?


Just i detta fallet så kommer jag bara skicka - exempelvis - 0x66 0x66 0x66 0x99 0x99 0x99 - i hex format alltså, plus en header på några tecken, men själva det som ska dekrypteras är de värdena som exempel.

Tänkte även använda mig av denna kryptering för ett trådat nätverk som jag jobbar med, då det var ganska smidigt att få in AES krypteringen. Men där vet jag att ett paket kommer se ut som liknande;

Kod: Markera allt

0x01 0x55 0xAA	0xBB	0xFF	0x32	0x00	0x00	0x00	0x00	0x00	0x00	0x00	0x00	0x04
dvs.. En hel del nollor / 0x00.

Visserligen ska ju det paketet krypteras, så det beror ju vidare på om AES krypteringen skapar något nollvärde / 0x00. Eller hur?
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 46974
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: AVR C - sträng hoppar in i annan, utan anledning!

Inlägg av TomasL »

Inte för att själva idén är dum som du har, men tror du inte att lösningen med att använda ett NULL tecken är bättre i detta fall?
Det är normalt att avsluta strängar med /0, men det gäller just strängar och enbart strängar där /0 normalt inte förekommer.
Skall du skicka data där /0 ingår, vilket är troligt om du använder kryptering, så måste du räkna tecken i stället och ha det som argument när du skall anropa sändfunktionen.
Användarvisningsbild
toffie
Inlägg: 1888
Blev medlem: 22 juli 2004, 21:38:07
Ort: Töreboda / Stockholm
Kontakt:

Re: AVR C - sträng hoppar in i annan, utan anledning!

Inlägg av toffie »

Alright! Så för mitt exempelpaket så får jag räkna antalet "bytes" eller är det synliga tecken. Om man räknar bytes så blir det 15, men ska man räkna synliga tecken så blir det 60. Men det borde vara bytes.. eller hur? Nu börjar det bli snurrigt :D

Kod: Markera allt

0x01 0x55 0xAA   0xBB   0xFF   0x32   0x00   0x00   0x00   0x00   0x00   0x00   0x00   0x00   0x04

En annan fråga som jag kom på som ni kanske kan hjälpa mig med. När jag nu använder AES krypteringen och dekrypterar ett "paket" så får jag ju en variabel med hela datan rakt av, om jag vill dela upp det byte för byte, hur gör jag då? Ska jag dela upp variabeln varje två tecken och lägga i separata variabler eller finns det något annat sätt? Vilken "split" funktion använder man i C i sådant fall?

I PHP så var det ju enkelt split(',', $variabelnamn) som gällde för att exempelvis dela upp en variabel som körde med kommatecken som delning. För att dela upp det varje två tecken får man väl köra count för att se antal tecken, sen en for loop och gå över variabeln och plocka två tecken åt gången som man trycker in i en ny variabel. Ni förstår säkert!

Någon idé om detta? :)
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 46974
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: AVR C - sträng hoppar in i annan, utan anledning!

Inlägg av TomasL »

Är inte 0xYY hexadecimal notation, och då är det ju en byte, eller skall du faktiskt skicka strängen "0xYY", då blir det ju fyra byte (+ avslut), men då funkar ju å andra sidan din befintliga funktion, eftersom det är texten "0xYY" du skickar, vilket jag inte tror du menar.
Användarvisningsbild
toffie
Inlägg: 1888
Blev medlem: 22 juli 2004, 21:38:07
Ort: Töreboda / Stockholm
Kontakt:

Re: AVR C - sträng hoppar in i annan, utan anledning!

Inlägg av toffie »

0xYY?

Tanken är att korrekta hexadecimala värden ska skickas - från 0x00 till 0xFF. Varje "byte" dvs, varje hexvärde "betyder" något i mitt protokoll. Exempelvis så har vi 0xAA som är adressbyte, 0xBB är huvudkommando och 0xFF är subkommando. 0x32 är ett inställningsvärde och sedan är resten 0 fram till 0x04 som ska tolkas som avslut på "paketet". Här ska jag visserligen, kom jag på nu, gå efter antal bytes och ta hand om paketet först när jag fått in alla 15 bytes. Avslutet med 0x04 är mest för att det blev så.. inte säkert att det ska vara så i fortsättningen.

Kod: Markera allt

0x01 0x55 0xAA   0xBB   0xFF   0x32   0x00   0x00   0x00   0x00   0x00   0x00   0x00   0x00   0x04
Men som sagt, att dela upp "paketet" byte för byte skulle ju vara nödvändigt. Som jag har det nu så ramlar byte för byte in i varsin variabel när de trillar in på UART linan, men det blir ju lite annorlunda om man får in ett AES krypterat paket och sen dekrypterar detta, då blir det en enda lång sträng som inte är uppdelad byte för byte längre.
Senast redigerad av toffie 14 juli 2015, 23:28:33, redigerad totalt 1 gång.
Skriv svar