Gast
#480998
Nabend, tja, jetzt ist es soweit und ich probiere ich mich an meinen ersten ernsthaften C-Projekt. Bis jetzt habe ich immer mit ASM gearbeitet und hatte nie Probleme. Im Code den ich hier Eingefügt habe werden über Portexpander (74HC595 für Out und 74HC165 für IN) 8 Kanäle zu je einem Byte für Eingang und Ausgang realisiert. Die Kanäle werden immer paarweise angesprochen (16Bit In/Out). Die Auswahl der Kanäle erfolgt über einen Hardware Decoder (74HC139) mit der Funktion PE_Select(). Gelesen wird mit PE_In() und geschrieben mit PE_Out(). Ich habe zum Test in main einfach Eingang auf Ausgang kopiert. Wenn ein Bit am Eingang gesetzt wird, wird dieses auch am Ausgang korrekt gesetzt. Aber im benachbarten Kanal wird es auch gesetzt und toggelt dort. (Die Bitnummer ist die gleiche.) Dieses Programm habe ich vorher in ASM realisiert und dort funktioniert alles so wie es soll. Ich habe so eine Ahnung das der Compiler die Variablen etwas am mixen ist? Das ganze läuft auf einen MEGA16 und programmieren tue ich unter AVR Studio mit WinAVR als C Compiler. Wenn jemand eine Ahnung/Idee hat wo mein Problem liegt wäre ich für einen Hinweis echt dankbar! mfg Lars Code ------------------------------------------------------------------------ #include <avr/io.h> #include <stdint.h> #include "eeprom_default.h" #define PE_Demux_A0 PD2 // Ausgang #define PE_Demux_A1 PD3 // Ausgang #define PE_Demux_A2 PD4 // Ausgang #define PE_CLK PD7 // Ausgang #define PE_Enable PD6 // Ausgang #define PE_SData_Out PD5 // Ausgang #define PE_Port PORTD #define PE_SData_In PINB4 // Eingang #define PE_Read_Write PB3 // Ausgang #define PE_Modul_Enable PB1 // Ausgang //Achtung - Signal ist invertiert #define PE_PortB PORTB //###################################################################### ######################### /* Funktionsdeklarationen */ void GPIO_INIT(void); void PE_Select(volatile uint8_t Port); void PE_Out(volatile uint8_t Byte); volatile uint8_t PE_In(void); //###################################################################### ######################### int main(void) { //start main GPIO_INIT(); while(1) { PE_Select(0); PE_Out(PE_In()); PE_Select(1); PE_Out(PE_In()); PE_Select(2); PE_Out(PE_In()); PE_Select(3); PE_Out(PE_In()); } } //end main //###################################################################### ######################### /* Initialisierung */ void GPIO_INIT(void) { // Adress Port für den Adressdemultiplexer konfigurieren. DDRD |= (1 << DDD2 | 1 << DDD3 | 1 << DDD4); // Portexpander Steuerports konfigurieren. DDRD |= (1 << DDD5 | 1 << DDD6 | 1 << DDD7); DDRB |= (1 << DDB1 | 1 << DDB3); PE_PortB |= (1<<PE_Modul_Enable); // IO Modul deaktivieren } //###################################################################### ######################### /* Portexpander Funktionen */ /* Diese Funktion setzt den gewünschten Portexpander. Die Aufrufvariable ist ein uint8_t mit den Bereich von 0-7 (andere Werte werden ignoriert). Pro IO-Modul werden 2 Portexpander Adr. benutzt. IO-Modul 0 = 0 & 1; IO-Modul 1 = 2 & 3; IO-Modul 2 = 4 & 5; IO-Modul 3 = 6 & 7; */ void PE_Select(volatile uint8_t Port) { switch(Port) { case 0: { PE_Port &= ~(1 << PE_Demux_A0 | 1 << PE_Demux_A1 | 1 << PE_Demux_A2); break; } case 1: { PE_Port |= (1 << PE_Demux_A0); PE_Port &= ~( 1 << PE_Demux_A1 | 1 << PE_Demux_A2); break; } case 2: { PE_Port |= (1 << PE_Demux_A1); PE_Port &= ~( 1 << PE_Demux_A0 | 1 << PE_Demux_A2); break; } case 3: { PE_Port |= (1 << PE_Demux_A0 | 1 << PE_Demux_A1); PE_Port &= ~(1 << PE_Demux_A2); break; } case 4: { PE_Port |= (1 << PE_Demux_A2); PE_Port &= ~( 1 << PE_Demux_A0 | 1 << PE_Demux_A1); break; } case 5: { PE_Port |= (1 << PE_Demux_A0 | 1 << PE_Demux_A2); PE_Port &= ~(1 << PE_Demux_A1); break; } case 6: { PE_Port |= (1 << PE_Demux_A1 | 1 << PE_Demux_A2); PE_Port &= ~(1 << PE_Demux_A0); break; } case 7: { PE_Port |= (1 << PE_Demux_A0 | 1 << PE_Demux_A1 | 1 << PE_Demux_A2); break; } } } // PE_Select /* Das Ausgabewort wird mit dem MSB zuerst ausgegeben. */ void PE_Out(volatile uint8_t Byte_Out) { volatile uint8_t i,temp = 0; PE_PortB &= ~(1<<PE_Read_Write); // Schreibmodus aktivieren PE_PortB &= ~(1<<PE_Modul_Enable); // IO Modul aktivieren for (i=0; i<=7; i++) { temp = Byte_Out & 0b10000000; if ( temp==0) PE_Port &= ~(1<< PE_SData_Out); else PE_Port |= (1<<PE_SData_Out); PE_Port |= (1<<PE_CLK); Byte_Out <<= 1; asm volatile ("nop"); PE_Port &= ~(1<<PE_CLK); } PE_Port |= (1<<PE_Enable); // Enable Impuls an PE_Port &= ~(1<< PE_SData_Out); // PE_SData_Out auf 0 setzten asm volatile ("nop"); PE_Port &= ~(1<<PE_Enable); // Enable Impuls aus PE_PortB |= (1<<PE_Modul_Enable); // IO Modul deaktivieren } volatile uint8_t PE_In(void) { volatile uint8_t i,Byte_In = 0; PE_PortB |= (1<<PE_Read_Write); // Lesemodus aktivieren PE_PortB &= ~(1<<PE_Modul_Enable); // IO Modul aktivieren PE_Port |= (1<<PE_Enable); // Enable Impuls an asm volatile ("nop"); PE_Port &= ~(1<<PE_Enable); // Enable Impuls aus for (i=0; i<=6; i++) { if (PINB & (1<<PE_SData_In)) { Byte_In = Byte_In | 0b00000001; } PE_Port |= (1<<PE_CLK); asm volatile ("nop"); PE_Port &= ~(1<<PE_CLK); Byte_In <<= 1; } if (PINB & (1<<PE_SData_In)) { Byte_In = Byte_In | 0b00000001; } PE_PortB |= (1<<PE_Modul_Enable); // IO Modul deaktivieren return Byte_In; }