⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hoarder.c

📁 用51单片机读取CF卡的程序。对许多项目有参考价值
💻 C
📖 第 1 页 / 共 3 页
字号:
// Hoarder board software http://vadim.www.media.mit.edu/Hoarder/Hoarder.htm
// Copyright (C) 2001-2002 MIT Media Laboratory
// Concept, design, and programming by Vadim Gerasimov <vadim@media.mit.edu>
// Code fragments by Paul Covell, Matthew Drake
// Ideas contributed by 
// Paul Covell, Ted Selker, Sandy Pentland, Richard DeVaul, 
// Brian Silverman, Tim Hirzel, Josh Weaver, Ivan Chardin 

#include <16F877.H>
#list
#include "Math32.c"

// Configuration bits for initial programming
#fuses   HS, NOPROTECT, WDT, PUT, BROWNOUT, NOLVP

// 20 MHz clock
#use delay (clock=20000000)

// up to 57.6kBaud (recommended 38.4) to be compatible with BiM2 transceiver 
// up to 115,2kBaud for cable connection
#use rs232 (baud=115200, xmit=PIN_C6, rcv=PIN_C7)

// Disable automatic TRIS programming for all ports
#use fast_io(a)  
#use fast_io(b)  
#use fast_io(c)
#use fast_io(d)
#use fast_io(e)

// for MIThril bus and I2C-enabled add-on boards
#use I2C (master, sda=PIN_C4, scl=PIN_C3, address=0xc0, SLOW)

// define for initial PIC programming to include the serial programming function
#define InitialProgram

// define only one: Rochester, ESL, GAME, or Tim
//#define Rochester
#define ESL // Every Sign of Life collect/broadcast
//#define GAME // Ball game broadcast
//#define Tim // Tim Hirzel's project data collection

// define OldSAK for boards earlier than NOV 2001
//#define OldSAK

// define DelayedWrite to use with IBM MicroDrive (TM)
//#define DelayedWrite

// CompactFlash pins
// 3 address lines (all others grounded)
  #define CF_A0      PIN_B0
  #define CF_A1      PIN_B1 
  #define CF_A2      PIN_B2
// data flow strobe signals
  #define CF_N_OE    PIN_B3
  #define CF_N_WE    PIN_B4
// card detect signal (high if card is not present)  
  #define CF_CD1     PIN_B7
  #define cf_out     input(CF_CD1)
// CF power switch  
#ifdef OldSAK
  #define CF_POWER   PIN_C0
#else
  #define CF_POWER   PIN_B6
#endif

// LED pins  
  #define CF_LED0    PIN_C1
  #define CF_LED1    PIN_C2

// EKG amplifier enable for BIOMETRICS add-on module   
  #define EKG_EN     PIN_C5

// Real time clock signals
// two lines shared with CF data bus
  #define RTC_RST    PIN_B5	   
  #define RTC_CLK    PIN_D0	   
  #define RTC_IO     PIN_D1	

// BiM transceiver pins TX-, RX-enable and Carrier Detect
// TX, RX data pins connected to UART
#ifdef OldSAK
  #define BIM_TX     PIN_E0   
  #define BIM_RX     PIN_E1   
  #define BIM_CD     PIN_E2 
#else
  #define BIM_TX     PIN_E2   
  #define BIM_RX     PIN_E1   
  #define BIM_CD     PIN_C0 
#endif  

#define RBIF     0x58
#define RCIF	   0x65
#define OERR	   0xC1
#define CREN	   0xC4

// Event button -- Tim Hirzel's project
#define BUTTON	 PIN_A4

#byte   SPBRG	   = 0x99
#byte   TXSTA	   = 0x98
#byte   PORTA	   = 0x05	
#byte   PORTB	   = 0x06	
#byte   PORTC	   = 0x07	

#byte CF_DATA   = 0x08  /* Port D */
#byte CF_DATA_TRIS = 0x88 /* Port D TRIS */

// 1-in 0-out
#define TRIS_A     0xFF  // 11111111 
#define TRIS_B     0x80  // 10000000 

#ifdef OldSAK
  #define TRIS_C     0xF8  // 11111000
  #define TRIS_C_SLEEP 0x80  // 10000000
  #define TRIS_E 0x04  // 0000x100
#else
  #define TRIS_C     0xD9  // 11011001 
  #define TRIS_C_SLEEP 0x81  // 10000001
  #define TRIS_E 0x01  // 0000x001
#endif

#define TRIS_D_IN  0xFF  // 11111111
#define TRIS_D_OUT 0x00  // 00000000 
#define TRIS_D_RTC_OUT 0xFC
#define TRIS_D_RTC_IN  0xFE

// Function Prototypes 
void print_prompt();
#separate void save_audio();
#separate void save_data();
#separate void send_data();
#separate void send_data_bim();
#separate void send_data_Tim();
#separate void send_player_info();
void led_off();
void led_red();
void led_green();
#separate boolean process_command();
void print_help();
int fromHex(char hex);
void set_default_signals();
void cf_task_file_read(int addr);
void cf_task_file_write(int addr, int data);
byte rtc_read(int addr);
void rtc_write(int addr, int data);
#separate boolean get_disk_configuration();
void cf_set_addr(int addr);


// Global variables

// Data file name on CF card
char const fname[12] = "ESL     DAT";
// A/D buffer
#define buf_size 32
long buffer[buf_size];
int buf_head;
int buf_count;
int ad_count;
boolean ad_on;
boolean audio;
long voltage;

int curData;  // Holds data to be sent
int curAddr;  // Holds address to be read/written

char sector[4]; // Current CF sector number for Read/Write operations
boolean disk_valid; // CF seems ok
boolean file_valid; // Data file seems ok

// FAT (file allocation table) variables
char data_start[4];
char fat_start[4]; // first sector of first copy of FAT
char dir_start[4]; // first sector of root directory
char data_sectors[4]; // number of data sectors
char data_file_size[4];
char sector_counter[4]; // to count down number of unused sectors in data file
byte sectors_per_cluster;
long root_entries; // number of entries in root directory
long cluster;

// Real time clock buffer
char time[8]; // hold all 8 time bytes from RTC chip
// Time in ms after last reset (if timer int set to 1kHz)
char ms[4]; // millisecond timer

char cmd; // last command character
long write_pos; // write position in current sector
long crc16; 


// self-programming function
// reprograms PIC thru serial port
// host sends pieces of code as:
// 1 byte header 0xAB
// 2 bytes start address
// 2 bytes (N) number of words to program
// N words (N*2 bytes) program words
// 
// after each program word function sends back 
// 1 if word programmed successfully
// 0 if not
//
// send non 0XAB byte to exit the cycle and restart Hoarder
//
#ifdef InitialProgram	
#ORG 0x1F00, 0x1FFF
void self_program()
{
  long addr, count, val, i;
  disable_interrupts(GLOBAL);
  while(getc()==0xAB) {
    *(&addr)=getc();
    *(&addr+1)=getc();
    *(&count)=getc();
    *(&count+1)=getc();
    for (i=0; i<count; i++) {
      *(&val)=getc();
      *(&val+1)=getc();
      if (val==read_program_eeprom(addr)) putc(1);
      else {
        write_program_eeprom(addr, val);
        if (val==read_program_eeprom(addr)) putc(1);
        else putc(0);
      }
      addr++;
      restart_wdt();
    }
  }
  #asm
  movlw    0 
  movwf	   0x0A
  goto     0		 	
  #endasm 
}
#endif

// jumps to self_program()
// normally called from command processor
// Note: if you want serial programming to work make sure you can always interrupt 
//       your program from serial port and have a command that calls this function  
#inline
void reprogram()
{
#ifdef InitialProgram
  self_program();
#else
  #asm
  movlw	0x18 
  movwf	0x0A
  goto 	0x700		 	
  #endasm 
#endif
}

// timer function
// increments ms counter
// performs timed AD conversion
// can do a lot of other neat stuff!
// normally interrupts 1000 times per second
// Note: in multisensor boards configuration can be set to 8000 times/sec
//       to sample audio
#int_timer2
void timer2() {
  static int i;
// resets watchdog timer
// Note: if you disable timer interrupt do this periodically somewhere else
//       otherwise WDT will reset PIC in ~2 seconds   
  restart_wdt();
//  inc32(ms);
  if (++ms[0]==0) if (++ms[1]==0) if (++ms[2]==0) ++ms[3]; 
  if (ad_on) {
#ifdef Tim
    if (ad_count==3) voltage=read_adc();
    if (ad_count==0)
#endif  	
    if (/*(ad_count==3) && */(buf_count<buf_size)) {
      i=(buf_head+buf_count)&0x1F;
      buffer[i]=read_adc();
      buf_count++;	
    }
    // else overflow  
    if (audio) ad_count=0;
    else {
      ad_count++;
      if (ad_count>3) ad_count=0;
    }
//#ifdef GAME   
//    if (ad_count==1) set_adc_channel(4); else set_adc_channel(ad_count);	
//#else
    set_adc_channel(ad_count);	
//#endif
  }
}

// Resets AD buffer
void purge_adc_buffer()
{
  buf_head=0;
  buf_count=0;
  set_adc_channel(0);
  ad_count=0;
}

// Green-Red... Happy?
void blink_happy()
{
  while (TRUE) {
    led_green();
    delay_ms(250); 
    led_red();
    delay_ms(250); 
  }
}

void blink_sad()
{
  while (TRUE) {
    led_red();
    delay_ms(250); 
    led_off();
    delay_ms(250); 
  }
}

// Turn off CF
void disable_cf()
{
  set_default_signals();
}

// exit if CF is plugged; otherwise sleep waking up on WDT to check for CF; 
void take_a_nap()
{
  if (input(CF_POWER)) {
    output_low(CF_POWER);
    delay_ms(10);
  }	
  disable_cf();
  do {
    while(cf_out) {	
      led_red();
      delay_ms(1);	
      CF_DATA=0;
      SET_TRIS_D(TRIS_D_OUT);
      set_tris_c(TRIS_C_SLEEP);
      led_off(); 	
      sleep();
    }   
    delay_ms(500);
  } while(cf_out); // make sure CF is still in after 0.5 sec 
  output_low(CF_POWER); // power up
  output_high(CF_N_OE);
  output_high(CF_N_WE);
  SET_TRIS_D(TRIS_D_IN);
  led_green();	
  delay_ms(250);
  led_off(); 	
  // Check CF card configuration
  disk_valid=get_disk_configuration();
}

boolean enable_cf()
{
  // sleep until CF is present
  take_a_nap();
  return TRUE; 
}


#define I2CWRITE 0b00000000
#define I2CREAD  0b00000001

void putI2C(int device, int data) 
{
  i2c_start();
  i2c_write(device);
  i2c_write(data);
  i2c_stop();
}

int getI2C(int device) 
{
  i2c_start();
  i2c_write(device | I2CREAD);
  _return_ = i2c_read();
  i2c_stop();
}

void send_hello()
{
  while (!input(RCIF)) printf("Hello! ");
}
  
void main()
{
  setup_adc_ports(A_ANALOG); // port A all analog inputs
  setup_adc(ADC_CLOCK_DIV_32); // set ADC clock
  setup_psp(PSP_DISABLED);

  set_default_signals(); // preset some of the signals

  SET_TRIS_A(TRIS_A); // set TRIS values
  SET_TRIS_B(TRIS_B);
  SET_TRIS_C(TRIS_C);
  SET_TRIS_D(TRIS_D_IN);
  SET_TRIS_E(TRIS_E);

  port_b_pullups(TRUE); // Should be enabled; Used for B6 and B7 (CF power and CF detection)
  setup_timer_2(T2_DIV_BY_4, 250, 5); // default timer: 1mS interval @ 20 MHz; see timer2()
  zero32(ms); // zero millisecond counter
  ad_on=FALSE;
  audio=FALSE;
  purge_adc_buffer();

//  enable_interrupts(INT_RB);  
  enable_interrupts(INT_TIMER2);  
  enable_interrupts(GLOBAL);
  
  disable_cf();
//  set_default_signals();
//  send_hello();
#ifdef GAME  
  puts("GAME");
  send_player_info();
#else  
//  take_a_nap();
#endif
#ifdef Rochester  
  puts("Roch");
  delay_ms(5000);
  save_audio();
#endif  
#ifdef ESL  
  puts("HackFest v odno slovo");
//  send_data_bim();
#endif  
#ifdef Tim  
  puts("Tim");
  send_data_Tim();
#endif  
  print_prompt();	
  while(TRUE)
  {
    led_off();
    process_command();
    led_red();	
    led_green();
    led_green();
//    if (cf_out) take_a_nap();
  }
}

void set_default_signals()
{
  // default RTC signals
  output_low(RTC_RST);
  output_low(RTC_CLK);
  output_low(RTC_IO); 
  // default CF power down signals
  output_low(CF_N_OE);
  output_low(CF_N_WE);
  cf_set_addr(0);
  output_high(CF_POWER);
  // default radio modem signals
  output_high(BIM_TX); // do not transmit
  output_high(BIM_RX); // do not recive
  // disable EKG amplifiers if present
  output_high(EKG_EN);
  // presumption of invalidity
  disk_valid=false;
}

// reset CF
#separate
void cf_reset()
{
  output_high(CF_POWER);
  delay_ms(500);
  output_low(CF_POWER);
}

// set CF port address (see task file in CF specs)
// Horder uses ports 0-7 to control CF
void cf_set_addr(int addr)
{
  output_bit(CF_A0, bit_test(addr, 0));
  output_bit(CF_A1, bit_test(addr, 1));
  output_bit(CF_A2, bit_test(addr, 2));
}

// write 1 byte into current CF port
void cf_write(int data)
{
  // set data	
  CF_DATA_TRIS = TRIS_D_OUT;
  CF_DATA = data;
  // Strobe write signal
  OUTPUT_LOW(CF_N_WE);
  OUTPUT_HIGH(CF_N_WE);
  CF_DATA_TRIS = TRIS_D_IN;
}

// read 1 byte from current CF port
int cf_read()
{
  CF_DATA_TRIS = TRIS_D_IN;
  // strobe read signal and get data
  output_low(CF_N_OE);
  _return_ = CF_DATA;
  output_high(CF_N_OE);
}

// skip bytes from current sector buffer
// assumes: CF port set to 0
void cf_read_skip(unsigned int count)
{
  CF_DATA_TRIS = TRIS_D_IN;
  do {
    output_low(CF_N_OE);
    output_high(CF_N_OE);
    count--;
  } while (count>0);
}

// write data to CF port addr
void cf_task_file_write(int addr, int data)
{
  cf_set_addr(addr);
  cf_write(data);
}

// read byte from CF port addr
int cf_task_file_read(int addr)
{
  cf_set_addr(addr);
  return(cf_read());
}

// enable nice power-saving features of Microdrive (see Microdrive specs)
// does nothing if used with regular CF memory cards
void enable_microdrive_write_cache()
{
  while ((cf_task_file_read(7)&0xC0)!=0x40);
  cf_task_file_write(1, 0x02);   // 0x02 = enable write cache  
  cf_task_file_write(6, 0xE0);     
  cf_task_file_write(7, 0xEF);   // set features command
  while ((cf_read()&0xC0)!=0x40);
  cf_task_file_write(1, 0xAA);   // 0xAA = enable read look ahead  
  cf_task_file_write(6, 0xE0);     
  cf_task_file_write(7, 0xEF);   // set features command
  while ((cf_read()&0xC0)!=0x40);
#ifdef DelayedWrite  
  cf_task_file_write(1, 0x07);   // 7 = enable delayed write  
  cf_task_file_write(6, 0xE0);     
  cf_task_file_write(7, 0xFA);   // set delayed write command
  while ((cf_read()&0x80)==0x80);
#endif  
}

// start reading CF sector
// global var sector indicates sector number
// after calling this function use cf_read() and cf_skip(int) 
// to read/skip 512 bytes from sector
void cf_start_sector_read()
{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -