Принципиальная схема устройства и перечень компонентов.
Приложение 2
Листинг
1) Работа с флеш
// #########################################################################
// Compiler: AVR-GCC 3.4.3
// #########################################################################
#include
#include
#include
#include «dos.h»
#define sbi (portn, bitn) ((portn)|=(1<<(bitn)))
#define cbi (portn, bitn) ((portn)&=~(1<<(bitn)))
// ######################################################
unsigned char MMCCommand (unsigned char command, unsigned long adress)
// ######################################################
{
SPI_WRITE(0xFF); //Dummy write
SPI_WAIT();
SPI_WRITE(command);
SPI_WAIT();
SPI_WRITE((unsigned char) (adress>>24)); //MSB of adress
SPI_WAIT();
SPI_WRITE((unsigned char) (adress>>16));
SPI_WAIT();
SPI_WRITE((unsigned char) (adress>>8));
SPI_WAIT();
SPI_WRITE((unsigned char) adress); //LSB of adress
SPI_WAIT();
SPI_WRITE(0xFF); //dummy checksum
SPI_WAIT();
SPI_WRITE(0xFF); // 16 bit response
SPI_WAIT();
SPI_WRITE(0xFF);
SPI_WAIT();
return SPDR; // only last 8 bits used
}
// ######################################################
unsigned char MMCReadSector (unsigned long sector, unsigned char *buf)
// ######################################################
{
unsigned int i;
unsigned char *p, by;
unsigned long startadr;
if (sector>=maxsect) return 1; //sectornumber too big
p=buf; //using a pointer is much faster than indexing buf[i]
MMC_CS_OFF();
//calculate startadress of the sector
startadr=sector * (unsigned long) BYTE_PER_SEC;
MMCCommand (MMC_READ_BLOCK, startadr);
do
{
SPI_WRITE(0xFF);
SPI_WAIT();
} while (SPDR!=0xFE); // wait for card response
//the following code looks very strange!
//the idea is not to stop the cpu while SPI module transfers data.
//you have 16 cpu cycles until transmission has finished!
//you can use this time to do something like storing your last data
//or get your next data out of memory, doing some loop overhead….
//don't wait for end of transmission until you have done something better;)
SPI_WRITE(0xFF); // shift in first byte
SPI_WAIT(); // we have to wait for the first byte, but ONLY for the first byte
by=SPDR; // get first byte, but store later!
SPI_WRITE(0xFF); // start shift in next byte
for (i=0; i< (BYTE_PER_SEC-1); i++) //execute the loop while transmission is running in background
{
// do the for() loop overhead at this point while SPI module shifts in new data
*p++=by; // store last byte in buffer while SPI module shifts in new data
SPI_WAIT(); // wait for next byte
by=SPDR; // get next byte, but store later!
SPI_WRITE(0xFF); // start shift in next byte
}
// last SPI_WRITE(0xFF); is shifting in crc part1 at this point
*p=by; // store last byte in buffer while SPI module shifts in crc part1
SPI_WAIT();
SPI_WRITE(0xFF); // shift in crc part2
SPI_WAIT();
MMC_CS_ON();
return 0;
}
// ######################################################
unsigned char MMCWriteSector (unsigned long sector, unsigned char *buf)
// ######################################################
{
unsigned int i;
unsigned char *p, by;
unsigned long startadr;
if (sector>=maxsect) return 1; //sectornumber too big
p=buf; //using a pointer is much faster than indexing buf[i]
MMC_CS_OFF();
//calculate startadress
startadr=sector * (unsigned long) BYTE_PER_SEC;
MMCCommand (MMC_WRITE_BLOCK, startadr);
SPI_WRITE(0xFF); // do we need this TWO dummy writes?
SPI_WAIT();
SPI_WRITE(0xFF);
SPI_WAIT();
SPI_WRITE(0xFE); // start block token for next sector
for (i=0; i
{
// do the for() loop overhead at this point while SPI module shifts out new data
by=*p++; // get next data from memory while SPI module shifts out new data
SPI_WAIT(); // wait for end of transmission
SPI_WRITE(by); // start shift out next byte
}
SPI_WAIT(); // wait til last byte is written to MMC
SPI_WRITE(0xFF); // 16 bit crc follows data
SPI_WAIT();
SPI_WRITE(0xFF);
SPI_WAIT();
SPI_WRITE(0xFF); // read response
SPI_WAIT();
by=SPDR & 0x1F;
if (by!= 0x05) // data block accepted?
{
MMC_CS_ON();
return 1;
}
do
{
SPI_WRITE(0xFF);
SPI_WAIT();
// } while (SPDR!=0xFF); // wait til busy is gone
} while (SPDR == 0x00); // wait til busy is gone
MMC_CS_ON();
return 0;
}
// ######################################################
unsigned char MMCIdentify(void)
// ######################################################
{
unsigned char by;
unsigned int i;
unsigned int c_size, c_size_mult, read_bl_len;
unsigned long drive_size;
// set directions of portpins used by MMC Card
sbi (DDRB, 1); //PB1 SCK output
cbi (PORTB, 1); //PB1 SCK set 0
cbi (DDRB, 3); //PB3 MISO input
cbi (PORTB, 3); //PB3 MISO set 0
sbi (DDRB, 2); //PB MOSI output
cbi (PORTB, 2); //PB MOSI set 0
sbi (MMC_CS_DDR, MMC_CS_PIN); //MMC_CS output
sbi (MMC_CS_PORT, MMC_CS_PIN); //MMC_CS set 1
//Init SPI with a very slow transfer rate first!
//SPCR SPI Controlregister
// SPIE=0; //No SPI Interrupt
// SPE=1; //SPI Enable
// DORD=0; //Send MSB first
// MSTR=1; //I am the master!
// CPOL=0; //SCK low if IDLE
// CPHA=0; //SPI Mode 0
// SPR1=1; //SPI Clock = f/128 = 125kHz @16MHz Clock
// SPR0=1; //or f/64 if SPI2X = 1 in SPSR register
SPCR=0x53;
//SPSR SPI Statusregister
// SPI2X=1; //Double speed for SPI = 250kHz @16MHz Clock
// SPSR=0x01;
SPSR=0x00;
for (i=0; i<10; i++)
{
SPI_WRITE(0xFF); // give min 74 SPI clock pulses before
// sending commands
SPI_WAIT();
}
MMC_CS_OFF();
//send CMD0 for RESET
SPI_WRITE (MMC_RESET); //command code CMD0
SPI_WAIT();
SPI_WRITE(0x00);
SPI_WAIT();
SPI_WRITE(0x00);
SPI_WAIT();
SPI_WRITE(0x00);
SPI_WAIT();
SPI_WRITE(0x00);
SPI_WAIT();
SPI_WRITE(0x95); // CMD0 needs a checksum!
SPI_WAIT();
SPI_WRITE(0xFF); // get 16 bit response high
SPI_WAIT();
SPI_WRITE(0xFF); // get 16 bit response low
SPI_WAIT();
//repeat CMD1 til result=0
do
{
by=MMCCommand (MMC_INIT, 0);
} while (by!=0);
//read CID
// MMCCommand (MMC_READ_CID, 0); // nothing really interesting here
//read CSD Card Specific Data
MMCCommand (MMC_READ_CSD, 0);
//This worked with extrememory MMC and takeMS SD
// SPI_WRITE(0xFF); // ignore response 0xFE
// SPI_WAIT();
// This waiting loop is for SanDisk 256MB SD
// Works with my other cards too
do
{
SPI_WRITE(0xFF);
SPI_WAIT();
} while (SPDR!=0xFE); // wait for card response
for (i=0; i<16; i++) //CSD has 128 bits -> 16 bytes
{
SPI_WRITE(0xFF);
SPI_WAIT();
by=SPDR;
// ShowHex(by);
dirbuf[i]=by;
}
SPI_WRITE(0xFF); // 16 bit crc follows data
SPI_WAIT();
SPI_WRITE(0xFF);
SPI_WAIT();
//here comes the hard stuff!
//calculate disk size and number of last sector
//that can be used on your mmc/sd card
c_size=dirbuf[6] & 0x03; //bits 1..0
c_size<<=10;
c_size+=(unsigned int) dirbuf[7]<<2;
c_size+=dirbuf[8]>>6;
by= dirbuf[5] & 0x0F;
read_bl_len=1;
read_bl_len<<=by;
by=dirbuf[9] & 0x03;
by<<=1;
by+=dirbuf[10] >> 7;
c_size_mult=1;
c_size_mult<<=(2+by);
drive_size=(unsigned long) (c_size+1) * (unsigned long) c_size_mult * (unsigned long) read_bl_len;
maxsect= drive_size / BYTE_PER_SEC;
MMC_CS_ON();
//switch to high speed SPI
// SPR1=0; //SPI Clock = f/4 = 4MHz @16MHz Clock
// SPR0=0; //or f/2 if SPI2X = 1 in SPSR register
SPCR=0x50;
//SPSR SPI Statusregister
// SPI2X=1; //Double speed for SPI = 8MHz @16MHz Clock
SPSR=0x01;
return 0;
}
2) Работа с микросхемой часов реального времени
// #########################################################################
// File: rtc.c
//
// Функции для работы с микросхемой реального времени
// RTC – 8564 JE
#########################################################################
// Compiler: AVR-GCC 4.1.1
// ##################################################################
#include
#include «rtc.h»
// инициализация RTC – 8564 JE
// инициализируем шину TWI (I2C)
void Init_Timer() {
TWBR = 29;
TWCR = (1<
}
// декодирование байта из формата BCD
unsigned char DECODER (char x) {
unsigned char y;
y=0;
if (x&0x80) y+=80;
if (x&0x40) y+=40;
if (x&0x20) y+=20;
if (x&0x10) y+=10;
if (x&0x08) y+=8;
if (x&0x04) y+=4;
if (x&0x02) y+=2;
if (x&0x01) y+=1;
return y;
}
// кодирование байта в формата BCD
unsigned char CODER (char x) {
unsigned char y;
y=0;
if (x>79) {y|=0x80; x-=80;}
if (x>39) {y|=0x40; x-=40;}
if (x>19) {y|=0x20; x-=20;}
if (x>9) {y|=0x10; x-=10;}
if (x>7) {y|=0x08; x-=8;}
if (x>3) {y|=0x04; x-=4;}
if (x>1) {y|=0x02; x-=2;}
if (x>0) {y|=0x01; x-=1;}
return y;
}
// чтение времени из RTC – 8564 JE
void Timer_Read() {
unsigned char d;
TWCR=(1<
while (! (TWCR & (1<
TWDR=SLA_W;
TWCR = (1<
while (! (TWCR & (1<
TWDR =0;
TWCR = (1<while (! (TWCR & (1<
TWDR =0;
TWCR = (1<
while (! (TWCR & (1<
TWDR =0;
TWCR = (1<while (! (TWCR & (1<
TWCR=(1<
while (! (TWCR & (1<
TWDR=SLA_R;
TWCR = (1<
while (! (TWCR & (1<
TWCR = (1<
while (! (TWCR & (1<
d=TWDR&0x7f;
clock.sec=DECODER(d);
TWCR = (1<
while (! (TWCR & (1<
d=TWDR&0x7f;
clock.min=DECODER(d);
TWCR = (1<
while (! (TWCR & (1<
d=TWDR&0x3f;
clock.hour=DECODER(d);
TWCR = (1<
while (! (TWCR & (1<
d=TWDR&0x3f;
clock.day=DECODER(d);
TWCR = (1<
while (! (TWCR & (1<
TWCR = (1<
while (! (TWCR & (1<
d=TWDR&0x1f;
clock.month=DECODER(d);
TWCR = (1<
while (! (TWCR & (1<
d=TWDR;
clock.year=DECODER(d);
TWCR = (1<
}
// установка времени в RTC – 8564 JE
void Timer_Set()
{
TWCR=(1<
while (! (TWCR & (1<
TWDR=SLA_W;
TWCR = (1<
while (! (TWCR & (1<
TWDR =0; //adress
TWCR = (1<
while (! (TWCR & (1<
TWDR =0; //write fist byte
TWCR = (1<
while (! (TWCR & (1<
TWDR =0; //write second byte
TWCR = (1<
while (! (TWCR & (1<
TWDR=CODER (clock.sec);
TWCR=(1<
while (! (TWCR & (1<
TWDR=CODER (clock.min);
TWCR=(1<
while (! (TWCR & (1<
TWDR=CODER (clock.hour);
TWCR=(1<
while (! (TWCR & (1<
TWDR=CODER (clock.day);
TWCR=(1<
while (! (TWCR & (1<
TWDR=1; //weekdays ignore
TWCR=(1<
while (! (TWCR & (1<
TWDR=CODER (clock.month);
TWCR=(1<
while (! (TWCR & (1<
TWDR=CODER (clock.year);
TWCR=(1<
while (! (TWCR & (1<
TWCR = (1<
}
3) работа с последовательными портами
// Compiler: AVR-GCC 3.4.3
// ##################################################################
#include
#include
#include
#include «serial0.h»
#define sbi (portn, bitn) ((portn)|=(1<<(bitn)))
#define cbi (portn, bitn) ((portn)&=~(1<<(bitn)))
//////////////////////////////////////////////////////////////////////////
// // Interrupt handlers
// // Global functions
// //////////////////////////////////////////////////////////////////////////
// // Initialize the serial port
// void SER0Init(void)
{
// Set TxD as output
sbi (TX0_DDR, TX0_PIN);
sbi (TX0_PORT, TX0_PIN);
// Enable RxD/TxD
UCSR0B=(1<
// Set baudrate
UBRR0H=(unsigned char) (UART0_BAUD_SELECT>>8);
UBRR0L=(unsigned char) (UART0_BAUD_SELECT);
// 8bit, 1 stop, no parity
UCSR0C=(1<
}
// Send character
// Waits until previous character is transmitted
void SER0Putc (unsigned char c)
{
// Wait until previous character is transmitted
while (bit_is_clear (UCSR0A, UDRE0))
;
UDR0=c;
}
// Send a string
void SER0Puts (unsigned char * s)
{
unsigned char c;
while((c=*s++))
{
if (c == '\n')
{
// Translate \n in \r\n
SER0Putc(0x0D);
SER0Putc(0x0A);
}
else
SER0Putc(c);
}
}
// Send a hexadecimal number
void SER0PutHex (unsigned char by)
{
unsigned char buff;
// High nibble
buff = by >> 4;
if (buff < 10)
buff += '0';
else
buff += 0x37;
SER0Putc(buff);
// Loz nibble
buff = by & 0x0f;
if (buff<10)
buff+='0';
else
buff+=0x37;
SER0Putc(buff);
}
// Get received character from buffer
// when no character is available the function
// will wait
unsigned char SER0Getc(void)
{
unsigned char c;
// Wait until at least 1 character is present
while (bit_is_clear (UCSR0A, RXC0))
;
c = UDR0;
return (c);
}
// Check of there are characters present
// rcnt is 0 when there are no characters
//
unsigned char SER0CharsPresent(void)
{
return bit_is_set (UCSR0A, RXC0);
}
Поделитесь с Вашими друзьями: |