PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : problem mit bitmanipulation



_maddin
29.07.2008, 18:12
hallo
ich habe ein glcd an meinem mega32 hängen, das bis vorhin noch super lief. ein port war für die daten zuständig, einer als CTRL port. jetzt brauchte ich am Datenport (PORTC) die SDA und SCL leitung. also habe ich statt PC0&PC1 PB0&PB1 mit dem datenport des lcd verlötet, weil die noch frei waren. dann hab ich das programm umgeschrieben, bis ich dachte, so müsste es funktionieren. die lötverbindungen sind einwandfrei, aber es tut sich nix. ich glaube ich habe einen einfachen fehler bei der bitmanipulation in diesen zeilen gemacht, ich komm aber nich drauf was es ist.
statt
DATAPORT=command;
steht jetzt


DATAPORT &=(1<<0)|(1<<1);
DATAPORT |= command&(~((1<<0)|(1<<1)));
DATAPORT2 &=~((1<<0)|(1<<1));
DATAPORT2 |= command&((1<<0)|(1<<1));

wo ist der denkfehler, tut mir etwas leid wenn die frage total dumm ist aber ich hab nen brett vorm kopf.
hier der komplette code:


#define DATAPORT PORTC
#define DATADDR DDRC
#define DATAPIN PINC
#define DATAPORT2 PORTB
#define DATADDR2 DDRB
#define DATAPIN2 PINB
#define CTRLPORT PORTB
#define CTRLDDR DDRB
#define RS 2
#define RW 3
#define E 4

#define lcd_busy _delay_us(2)

void lcd_enable(void){
// Erzeugt eine fallende Flanke am Enable-Pin

CTRLPORT |= (1<<E);
lcd_busy;
CTRLPORT &= ~(1<<E);
lcd_busy;
}

void lcd_writecommand(uint8_t command) {
// Kommandobyte -> HD61830

lcd_busy;
CTRLPORT &= ~(1<<RW); // R/W auf logisch 0 -> W
CTRLPORT |= (1<<RS); // RS auf logisch 1 -> aktiv
DATAPORT &=(1<<0)|(1<<1);
DATAPORT |= command&(~((1<<0)|(1<<1))); // übergebenes Kommandobyte wird ausgegeben
DATAPORT2 &=~((1<<0)|(1<<1));
DATAPORT2 |= command&((1<<0)|(1<<1)); // übergebenes Kommandobyte wird ausgegeben
lcd_enable();
}

void lcd_writedata(uint8_t data) {
// Datenbyte -> HD61830

lcd_busy;
CTRLPORT &= ~(1<<RW); // R/W auf logisch 0 -> W
CTRLPORT &= ~(1<<RS); // RS auf logisch 0 -> inaktiv
DATAPORT &=(1<<0)|(1<<1);
DATAPORT |= data&(~((1<<0)|(1<<1))); // übergebenes Kommandobyte wird ausgegeben
DATAPORT2 &=~((1<<0)|(1<<1));
DATAPORT2 |= data&((1<<0)|(1<<1)); // übergebenes Kommandobyte wird ausgegeben
lcd_enable();
}

void lcd_send(uint8_t command, uint8_t data) {
// Kombination aus Kommando- und Datenbyte

lcd_writecommand(command);
lcd_writedata(data);
}

void lcd_init(unsigned char modus){
// Initialisiert das Display

DATADDR |= ~((1<<0)|(1<<1)); // Datenport wird als Ausgang deklariert
DATADDR2 |= (1<<0)|(1<<1); // Datenport wird als Ausgang deklariert
CTRLDDR |= (1<<RW)|(1<<RS)|(1<<E); // Kommandoport wird als Ausgang deklariert

if(modus == 'c'){
// Charaktermodus

lcd_send(0x00, 0x30); // Mode Control
lcd_send(0x01, 0x75); // Set Character Pitch
lcd_send(0x02, 0x27); // Set Number of Characters
lcd_send(0x03, 0x80); // Set Number of Time Divisions
lcd_send(0x04, 0x07); // Set Cursor Position
}
else{
// Grafikmodus

lcd_send(0x00, 0x32); // Mode Control
lcd_send(0x01, 0x07); // number of bits of 1-byte display data to be displayed
lcd_send(0x02, 0x1d); // number of horizontal bytes
lcd_send(0x03, 0x80); // Set Number of Time Divisions
}

lcd_send(0x08, 0x00); // Set Display Start Low Order Address
lcd_send(0x09, 0x00); // Set Display Start High Order Address

lcd_clear(modus);
}

void lcd_clear(unsigned char modus){
// Löscht das Display

lcd_gotoxy(modus, 0, 0); // Cursor an den Anfang setzen

if(modus == 'c'){
// Charaktermodus

for(uint16_t i=0; i<640; i++) // Alle Chars durchlaufen und löschen
lcd_send(0x0c, 0x20);
}
else{
// Grafikmodus

for(uint16_t i=0; i<3840; i++) // Alle Bytes durchlaufen und löschen
lcd_send(0x0c, 0x00);
}

lcd_gotoxy(modus, 0, 0); // Cursor an den Anfang setzen
}

void lcd_gotoxy(unsigned char modus, uint8_t x, uint8_t y){
// Setzt den Cursor an eine bestimmte Position

uint16_t adress;

if(modus == 'c'){
// Charaktermodus
adress = (y * 40) + x;
}

else{
// Grafikmodus
adress = (y * 30) + x;
}

lcd_send(0x0a, (uint8_t)(adress)); // Set Cursor Address (Low Order)
lcd_send(0x0b, (uint8_t)(adress >> 8)); // Set Cursor Address (High Order)
}

void lcd_setdot(uint8_t x, uint8_t y){
// Setzt ein Pixel an einer bestimmten Position

lcd_gotoxy('g', (x >> 3), y);
lcd_send(0x0f, (x & 0x07));
}

void lcd_cleardot(uint8_t x, uint8_t y){
// Löscht ein Pixel an einer bestimmten Position

lcd_gotoxy('g', (x >> 3), y);
lcd_send(0x0e, (x & 0x07));
}

void lcd_putc(char c){
static char line=0;
if((c == 'ä') | ( c == 'Ä' ) ){
lcd_send(0x0c,0xE1);
}
else if((c == 'ü') | ( c == 'Ü' ) ){
lcd_send(0x0c,0xF5);
}
else if((c == 'ö') | ( c == 'Ö' ) ){
lcd_send(0x0c,0xEF);
}
else if((c == '\n') | ( c == '\r' )){
line++;
if(line==16) line=0;
lcd_gotoxy('c',0,line);
}
else lcd_send(0x0c,c);
}

void lcd_puts(char *string){
uint8_t i=0;
char c = string[0];

while(c != 0) {
lcd_putc(c);
c = string[++i];
}
}

char swapbits(char c){
char swap=0;
for(char bit=0;bit<8;bit++) if(c&(1<<bit)) swap|=(1<<(7-bit));
return swap;
}

void lcd_picture(char* byte){
for(short counter=0;counter<3840;counter++) {
lcd_send(0x0c,swapbits(pgm_read_byte(byte)));
byte++;
}
}

void glcd_puts(unsigned short x, unsigned short y, char *string){
uint8_t i=0;
char c = string[0];
unsigned short xpos=x, ypos=y;

while(c != 0) {
glcd_putc(xpos,ypos,c);
xpos+=6;
if(c=='\n'){
xpos=x;
ypos+=8;
}
c = string[++i];
}
}

void glcd_putc(unsigned short x, unsigned short y, char character) {
unsigned char fontIndex, i, j;

/* The 5x7 character set starts at the '!' character (ASCII index
* number 33) so we subtract 32 from the ASCII character to find the
* index in the 5x7 font table. */
fontIndex = character-32;
/* If the index is out of bounds, bail out */
if (fontIndex > 94)
return;

for (i = 0; i < FONT_WIDTH; i++) {
for (j = 0; j < FONT_HEIGHT; j++) {
/* Check if the bit/pixel is set, paint accoringly to
* the screen */
if (pgm_read_byte(&Font5x7[FONT_WIDTH*fontIndex+i] ) & (1<<j))
lcd_setdot(x, y+j);
else
lcd_cleardot(x, y+j);
}
/* Move the LCD cursor through the font width as well */
x++;
}
}

danke schonmal

SprinterSB
29.07.2008, 19:02
Der Zugriff ist nicht-atomar. Wenn einer der Ports auch per ISR verändert wird, kann das Probleme machen
Während des Setzens können je nach Device ungültige Kommandos entstehen? Vorher änderten sich ja alle Pins mit einem Schlag, was jetzt nicht mehr der Fall ist. Das Problem wird vielleicht abgemildert durch



PORT = (PORT & 0b11) | (command & ~0b11);


weil dann im Gegensatz zu Deiner Lösung nur 1x gelesen und 1x geschrieben wird (bei Dir 2x).

DDR ist gesetzt?

_maddin
29.07.2008, 23:12
1. stimmt aber ich habe keine interrupts aktiviert
2. ist egal da das ganze nur bei einem enable impuls übertragen wird
3. DDR ist gesetzt
danke trotzdem

zerush
30.07.2008, 00:12
Also rein logisch gesehen ist das schon richtig was du gemacht hast, aber übersichtlicher ist es auf jeden Fall in der Weise wie SprinterSB es geschrieben hat. (wobei ich anstatt 0b11 lieber 0x3 schreiben würde, versteht der gcc die Schreibweise 0b... ?)

Im Zweifelsfall, auch zum Testen der Verbindungen, kannst du ja einfach mal command = 0xFF anlegen und an allen Pins messen ob ein high Pegel anliegt..., vielleicht ist ja doch ne kalte Lötstelle oder sowas.

_maddin
30.07.2008, 00:37
hi
der gcc versteht die schreibweise 0b...., ist aber nicht standardkonform deshalb mag ichs nicht mehr so gerne.

das problem hat sich irgendwie von selbst gelöst. ich habe keine erklärung aber es geht jetzt.
danke für eure hilfe.
LG maddin