habe hier mal ein programm zusammengestellt aus auszügen für die gameboy-cam in winavr-c. die daten werden bei mir seriell mit 9600baud zum pc übertragen zum programm von tobi. ich habe ein AVR16 mit 8mhz intern und den adc-port-a0 benutzt.
adc.h :
Code:
#define ADCchannel_init DDRA=0x00 // ADC Port als Eingang deklarieren
#define ADCinit ADCSRA|=_BV(ADEN) // Teilt dem Board mit das der jeweilige Port für ADC verwendet wird
#define ADCdisable ADCSRA &=~_BV(ADEN) // machs das vorherige wieder rückgänig
#define ADCstart ADCSRA|=_BV(ADSC) // startet eine konvertierung auf dem gewünschten Kannal/Pin
#define ADCfree ADCSRA|=_BV(ADATE) // schaltet den freilaufenden Modus ein
#define ADCvintern ADMUX|=_BV(REFS0) // interne Spannungsversorgung
#define ADCinterrupt_on ADCSRA|=_BV(ADIE) // ADC interrupt wird freigeschalten
#define ADCprescaler_2 ADCSRA |=_BV(ADPS0) // gewünschter Teilungsfaktor/Prescaler
#define ADCprescaler_4 ADCSRA|=_BV(ADPS1)
#define ADCprescaler_8 ADCSRA=_BV(ADPS1) | _BV(ADPS0)
#define ADCprescaler_16 ADCSRA|=_BV(ADPS2)
#define ADCprescaler_32 ADCSRA=_BV(ADPS2) | _BV(ADPS0)
#define ADCprescaler_64 ADCSRA=_BV(ADPS2) | _BV(ADPS1)
#define ADCprescaler_128 ADCSRA=_BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0)
#define ADCprescaler_reset ADCSRA = ~_BV(ADPS2) & ~_BV(ADPS1) & ~_BV(ADPS0)
#define ADCchannel_1 //gewünschter Kannal z.B bei ATmega32 PINA0 - PINA7
#define ADCchannel_2 ADMUX|=_BV(MUX0) // bei nicht freilaufen muss ADCchannel_x vor
#define ADCchannel_3 ADMUX|=_BV(MUX1) // ADCstart kommen dann kann man mit getadc() der
#define ADCchannel_4 ADMUX= _BV(MUX1) | _BV(MUX0) // Adcwert des gewählten Kannals auslesen
#define ADCchannel_5 ADMUX|=_BV(MUX2)
#define ADCchannel_6 ADMUX= _BV(MUX2) | _BV(MUX0)
#define ADCchannel_7 ADMUX= _BV(MUX2) | _BV(MUX1)
#define ADCchannel_8 ADMUX= _BV(MUX2) | _BV(MUX1) | _BV(MUX0)
#define ADCchannel_reset ADMUX= ~_BV(MUX2) & ~_BV(MUX1) & ~_BV(MUX0)
uint16_t getadc(void)
{
while (ADCSRA & _BV(ADSC)) {}
return ADC;
}
gameboy-cam:
Code:
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <string.h>
#include <stdint.h>
#include <avr/delay.h>
#include "adc.h"
#define READ 1
#define WRITE 2
#define USART_BAUD_RATE 9600
#define USART_BAUD_SELECT (F_CPU/(USART_BAUD_RATE*16l)-1)
#define GBPORT PORTB
#define GBDDR DDRB
#define GBPIN PINB
#define CCLK 7
#define CLOAD 6
#define CSIN 5
#define CREAD 4
#define CSTART 1
#define CRESET 0
void delay_us(uint16_t us)
{
uint16_t zaehler;
while (us)
{
zaehler = F_CPU / 5000000;
while (zaehler)
{
asm volatile ("nop");
zaehler--;
}
us--;
}
}
void usart_init(int Enable, int Interupts)
{
if (Enable & READ) UCSRB = (1<<RXEN);
if (Enable & WRITE) UCSRB |= (1<<TXEN);
if (Interupts & READ) UCSRB |= (1<<RXCIE);
if (Interupts & WRITE) UCSRB |= (1<<TXCIE);
UBRRL = (unsigned char) USART_BAUD_SELECT;
}
void usart_writeChar(unsigned char c)
{
while (!(UCSRA & (1<<UDRE))) {}
UDR = c;
while(!(UCSRA & (1<<TXC))) {}
}
void usart_writeString(unsigned char *string) {
while (!(UCSRA & (1<<UDRE))) {}
while ( *string)
usart_writeChar(*string++);
}
// Laden der Register der gbcam
void gbcam_load_register(uint8_t adresse, uint8_t daten)
{
/* 3-Bit Adresse und 8-Bit Daten
Die Übertragung erfolgt über ein syncrones Protkoll mit CCLK, CSIN und CLOAD */
uint8_t i;
adresse &= 0x07;
// Übertragen der Adresse ( 3-Bit )
for (i=0;i<3;i++)
{
if ( ( adresse & 0x04 ) > 0 ) {
GBPORT |= (1<<CSIN);
}
adresse <<= 1;
GBPORT |= (1<<CCLK);
delay_us(10);
GBPORT &= ~(1<<CCLK);
delay_us(1);
GBPORT &= ~(1<<CSIN);
delay_us(1);
}
// Übertragen der Daten ( 8-Bit )
for (i=0;i<8;i++)
{
if ( ( daten & 0x80 ) > 0 )
GBPORT |= (1<<CSIN);
daten <<= 1;
GBPORT |= (1<<CCLK);
/* Beim letzen Bit muß zusätzlich die CLOAD Leitung gesetzt werden,
Nachdem CCLK gesetzt wurde */
delay_us(5);
if (i == 7) {
PORTB |= (1<<CLOAD);
}
delay_us(5);
GBPORT &= ~(1<<CCLK);
delay_us(1);
GBPORT &= ~((1<<CSIN)|(1<<CLOAD));
delay_us(1);
}
}
// Starten der Aufnahme
void gbcam_start(void)
{
// Startsignal erzeugen
GBPORT |= (1<<CSTART);
delay_us(1);
GBPORT |= (1<<CCLK);
delay_us(10);
GBPORT &= ~(1<<CSTART);
delay_us(1);
GBPORT &= ~(1<<CCLK);
delay_us(1);
}
// Kamera zurücksetzen
void gbcam_reset(void)
{
// Resetleitung auf Low ziehen
GBPORT &= ~(1<<CRESET);
delay_us(1);
GBPORT |= (1<<CCLK);
delay_us(10);
GBPORT |= (1<<CRESET);
delay_us(1);
GBPORT &= ~(1<<CCLK);
delay_us(1);
}
// Intitialisieren der Gameboy Kamera
void gbcam_init(void)
{
GBDDR = (1<<CCLK)|(1<<CLOAD)|(1<<CSIN)|(1<<CSTART)|(1<<CRESET);
GBPORT = (1<<CRESET)|(1<<CREAD);
gbcam_reset();
/* Laden der Register der Gameboy Kamera,
Einstellungen für ein normales Bild */
gbcam_load_register( 0x00,0);
// 000 GAIN
gbcam_load_register( 0x01, 7);
// Belichtungszeit
gbcam_load_register( 0x02, 54);
gbcam_load_register( 0x03, 1 );
gbcam_load_register( 0x04, 1 );
gbcam_load_register( 0x05, 0 );
gbcam_load_register( 0x06, 1 );
gbcam_load_register( 0x07, 7 );
}
int main (void)
{
char wert_str[10];
uint16_t adc_wert;
usart_init( (READ + WRITE) , READ);
ADCchannel_init;
ADCinit;
ADCprescaler_16;
ADCchannel_1;
gbcam_reset();
gbcam_init();
gbcam_start();
/* Warten bis die gbcam bereit ist */
while ( ( GBPIN & (1<<CREAD) ) == 0 )
{
GBPORT |= (1<<CCLK);
delay_us(1);
GBPORT &= ~(1<<CCLK);
delay_us(1);
}
// 16384 Pixel auslesen
while( ( GBPIN & (1<<CREAD ) ) != 0 )
{
GBPORT |= (1<<CCLK);
delay_us(1);
// AD Wandler starten
ADCstart;
adc_wert=getadc();
// Daten einlesen
itoa( adc_wert,wert_str, 10);
usart_writeString(wert_str);
GBPORT &= ~(1<<CCLK);
delay_us(1);
}
}
mfg pebisoft
Lesezeichen