📄 mmc_datalogger.c
字号:
typedef struct {
unsigned char command_byte; // OpCode;
unsigned char arg_required; // Indicates argument requirement;
unsigned char CRC; // Holds CRC for command if necessary;
unsigned char trans_type; // Indicates command transfer type;
unsigned char response; // Indicates expected response;
unsigned char var_length; // Indicates varialble length transfer;
} COMMAND;
// Command table for MMC. This table contains all commands available in SPI
// mode; Format of command entries is described above in command structure
// definition;
COMMAND code commandlist[25] = {
{ 0,NO ,0x95,CMD,R1 ,NO }, // CMD0; GO_IDLE_STATE: reset card;
{ 1,NO ,0xFF,CMD,R1 ,NO }, // CMD1; SEND_OP_COND: initialize card;
{ 9,NO ,0xFF,RD ,R1 ,NO }, // CMD9; SEND_CSD: get card specific data;
{10,NO ,0xFF,RD ,R1 ,NO }, // CMD10; SEND_CID: get card identifier;
{12,NO ,0xFF,CMD,R1 ,NO }, // CMD12; STOP_TRANSMISSION: end read;
{13,NO ,0xFF,CMD,R2 ,NO }, // CMD13; SEND_STATUS: read card status;
{16,YES,0xFF,CMD,R1 ,NO }, // CMD16; SET_BLOCKLEN: set block size;
{17,YES,0xFF,RD ,R1 ,NO }, // CMD17; READ_SINGLE_BLOCK: read 1 block;
{18,YES,0xFF,RD ,R1 ,YES}, // CMD18; READ_MULTIPLE_BLOCK: read > 1;
{24,YES,0xFF,WR ,R1 ,NO }, // CMD24; WRITE_BLOCK: write 1 block;
{25,YES,0xFF,WR ,R1 ,YES}, // CMD25; WRITE_MULTIPLE_BLOCK: write > 1;
{27,NO ,0xFF,CMD,R1 ,NO }, // CMD27; PROGRAM_CSD: program CSD;
{28,YES,0xFF,CMD,R1b,NO }, // CMD28; SET_WRITE_PROT: set wp for group;
{29,YES,0xFF,CMD,R1b,NO }, // CMD29; CLR_WRITE_PROT: clear group wp;
{30,YES,0xFF,CMD,R1 ,NO }, // CMD30; SEND_WRITE_PROT: check wp status;
{32,YES,0xFF,CMD,R1 ,NO }, // CMD32; TAG_SECTOR_START: tag 1st erase;
{33,YES,0xFF,CMD,R1 ,NO }, // CMD33; TAG_SECTOR_END: tag end(single);
{34,YES,0xFF,CMD,R1 ,NO }, // CMD34; UNTAG_SECTOR: deselect for erase;
{35,YES,0xFF,CMD,R1 ,NO }, // CMD35; TAG_ERASE_GROUP_START;
{36,YES,0xFF,CMD,R1 ,NO }, // CMD36; TAG_ERASE_GROUP_END;
{37,YES,0xFF,CMD,R1 ,NO }, // CMD37; UNTAG_ERASE_GROUP;
{38,YES,0xFF,CMD,R1b,NO }, // CMD38; ERASE: erase all tagged sectors;
{42,YES,0xFF,CMD,R1b,NO }, // CMD42; LOCK_UNLOCK;
{58,NO ,0xFF,CMD,R3 ,NO }, // CMD58; READ_OCR: read OCR register;
{59,YES,0xFF,CMD,R1 ,NO } // CMD59; CRC_ON_OFF: toggles CRC checking;
};
//-----------------------------------------------------------------------------
// Global VARIABLES
//-----------------------------------------------------------------------------
xdata LONG Result = {0L}; // ADC0 decimated value
xdata LOG_ENTRY LogRecord; // Memory space for each log entry
xdata unsigned long uLogCount; // Current number of table entries
LOG_ENTRY xdata *pLogTable; // Pointer to buffer for table entries
xdata STATE State = RESET; // System state variable; Determines
// how log update function will exec;
xdata unsigned long PHYSICAL_SIZE; // MMC size variable; Set during
// initialization;
xdata unsigned long LOG_SIZE; // Available number of bytes for log
// table;
xdata unsigned long PHYSICAL_BLOCKS; // MMC block number; Computed during
// initialization;
xdata char LOCAL_BLOCK[BUFFER_SIZE];
xdata char SCRATCH_BLOCK[PHYSICAL_BLOCK_SIZE];
xdata char error;
//-----------------------------------------------------------------------------
// Function PROTOTYPES
//-----------------------------------------------------------------------------
void main (void);
// Support Subroutines
void MENU_ListCommands (void); // Outputs user menu choices via UART
// Logging Subroutines
void LogUpdate (void); // Builds MMC log table
unsigned long LogFindCount(); // Returns current number of log entries
void LogErase (void); // Erases entire log table
void LogPrint (void); // Prints log through UART
void LogInit (LOG_ENTRY *pEntry); // Initializes area for building entries
// High Level MMC_FLASH Functions
void MMC_FLASH_Init (void); // Initializes MMC and configures it to
// accept SPI commands;
// Reads <length> bytes starting at
// <address> and stores them at <pchar>;
unsigned char MMC_FLASH_Read (unsigned long address, unsigned char *pchar,
unsigned int length);
// Clears <length> bytes starting at
// <address>; uses memory at <scratch>
// for temporary storage;
unsigned char MMC_FLASH_Clear (unsigned long address, unsigned char *scratch,
unsigned int length);
// Writes <length> bytes of data at
// <wdata> to <address> in MMC;
// <scratch> provides temporary storage;
unsigned char MMC_FLASH_Write (unsigned long address, unsigned char *scratch,
unsigned char *wdata, unsigned int length);
// Clears <length> bytes of FLASH
// starting at <address1>; Requires that
// desired erase area be sector aligned;
unsigned char MMC_FLASH_MassErase (unsigned long address1,
unsigned long length);
// Low Level MMC_FLASH_ Functions
// Decodes and executes MMC commands;
// <cmd> is an index into the command
// table and <argument> contains a
// 32-bit argument if necessary; If a
// data operation is taking place, the
// data will be stored to or read from
// the location pointed to by <pchar>;
unsigned int MMC_Command_Exec (unsigned char cmd, unsigned long argument,
unsigned char *pchar);
// Initialization Subroutines
void SYSCLK_Init (void);
void PORT_Init (void);
void UART0_Init (void);
void ADC0_Init (void);
void Soft_Init (void);
void Timer0_Init (int counts);
void Timer2_Init (int counts);
void SPI_Init (void);
// Interrupt Service Routines
void ADC0_ISR (void);
void Soft_ISR (void);
//-----------------------------------------------------------------------------
// MAIN Routine
//-----------------------------------------------------------------------------
void main (void) {
idata char key_press; // Input character from UART;
// Disable Watchdog timer
PCA0MD &= ~0x40; // WDTE = 0 (clear watchdog timer
// enable);
PORT_Init (); // Initialize crossbar and GPIO;
SYSCLK_Init (); // Initialize oscillator;
UART0_Init (); // Initialize UART0;
SPI_Init (); // Initialize SPI0;
Timer2_Init (SYSCLK/SAMPLE_RATE); // Init Timer2 for 16-bit autoreload;
ADC0_Init (); // Init ADC0;
Soft_Init (); // Initialize software interrupts;
MMC_FLASH_Init(); // Initialize MMC card;
AD0EN = 1; // enable ADC0;
State = RESET; // Set global state machine to reset
// state;
// Initialize log table buffer pointer
pLogTable = (LOG_ENTRY xdata *)LOCAL_BLOCK;
uLogCount = LogFindCount(); // Find current number of log table
// entries;
printf ("\n"); // Print list of commands;
MENU_ListCommands ();
State = STOPPED; // Global state is STOPPED; no data
// is being logged;
EA = 1; // Enable global interrupts;
while (1) // Serial port command decoder;
{
key_press = getchar(); // Get command character;
key_press = tolower(key_press); // Convert to lower case;
switch (key_press)
{
case 'c': // Clear log;
if(State == STOPPED) // Only execute if not logging;
{
printf ("\n Clear Log\n");
LogErase(); // erase log entries;
uLogCount = LogFindCount();// update global log entry count;
}
break;
case 'd': // Display log;
if(State == STOPPED) // Only execute if not logging;
{
printf ("\n Display Log\n");
LogPrint(); // Print the log entries;
}
break;
case 'i': // Init RTC;
if(State == STOPPED) // Only execute if not logging;
{
printf ("\n Init RTC values\n");
EA = 0; // Disable interrupts;
LogInit(&LogRecord); // Clear current time;
EA = 1; // Reenable interrupts;
}
break;
case 'p': // Stop logging;
if(State != STOPPED) // Only execute if not stopped already;
{
State = FINISHED; // Set state to FINISHED
printf ("\n Stop Logging\n");
while(State != STOPPED){} // Wait for State = STOPPED;
}
break;
case 's': // Start logging
if(State == STOPPED) // Only execute if not logging;
{
printf ("\n Start Logging\n");
State = RUNNING; // Start logging data
}
break;
case '?': // List commands;
if(State == STOPPED) // Only execute if not logging;
{
printf ("\n List Commands\n");
MENU_ListCommands(); // List Commands
}
break;
default: // Indicate unknown command;
if(State == STOPPED) // Only execute if not logging;
{
printf ("\n Unknown command: '%x'\n", key_press);
MENU_ListCommands(); // Print Menu again;
}
break;
} // switch
} // while
}
//-----------------------------------------------------------------------------
// Support Subroutines
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// MENU_ListCommands
//-----------------------------------------------------------------------------
// This routine prints a list of available commands.
//
void MENU_ListCommands (void)
{
printf ("\nData logging example version %s\n", VERSION);
printf ("Copyright 2004 Silicon Laboratories.\n\n");
printf ("Command List\n");
printf ("===============================================\n");
printf (" 'c' - Clear Log\n");
printf (" 'd' - Display Log\n");
printf (" 'i' - Init RTC\n");
printf (" 'p' - Stop Logging\n");
printf (" 's' - Start Logging\n");
printf (" '?' - List Commands\n");
printf ("\n");
}
//-----------------------------------------------------------------------------
// Logging Subroutines
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// LogUpdate()
//-----------------------------------------------------------------------------
// This routine is called by the ADC ISR at ~1Hz if State == RUNNING or
// FINISHED. Here we read the decimated ADC value, convert it to temperature
// in hundredths of a degree C, and add the log entry to the log table buffer.
// If the buffer is full, or the user has stopped the logger, we must commit
// the buffer to the MMC FLASH. <State> determines if the system is logging
// normally (State == RUNNING), or if the user has stopped the logging
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -