📄 mmc_datalogger.c
字号:
//-----------------------------------------------------------------------------
// MMC_DataLogger.c
//-----------------------------------------------------------------------------
// Copyright 2004 Silicon Laboratories
//
// AUTH: BW / JS / GV
// DATE: 08 MAR 04
//
// This program shows an example of a data logging application that maintains
// the log on an MMC card.
//
// Control Function:
//
// The system is controlled via the hardware UART, operating at a baud rate
// determined by the constant <BAUDRATE>, using Timer1 overflows as the baud
// rate source. The commands are as follows (not case sensitive):
// 'c' - Clear Log
// 'd' - Display Log
// 'i' - Init RTC
// 'p' - Stop Logging
// 's' - Start Logging
// '?' - List Commands
//
// Sampling Function:
//
// The ADC is configured to sample the on-chip temperature sensor at 4.096kHz,
// using Timer0 (in 8-bit auto-reload mode) as the start-of-conversion source.
// The ADC result is accumulated and decimated by a factor of 4096, yielding
// a 16-bit resolution quantitity from the original 10-bit sample at an
// effective output word rate of about 1Hz. This decimated value is
// stored in the global variable <result>.
//
// A note about oversampling and averaging as it applies to this temp
// sensor example: The transfer characteristic of the temp sensor on the
// 'F320 family of devices is 2.86mV/C. The LSB size of the ADC using the
// internal VREF (2.43V) as its voltage reference is 2.3mV/code.
// This means that adjacent ADC codes are about ~1 degrees C apart.
//
// If we desire a higher temperature resolution, we can achieve it by
// oversampling and averaging (See AN118 on the Silicon Labs website). For
// each additional bit of resolution required, we must oversample by a power
// of 4. For example, increasing the resolution by 4 bits requires
// oversampling by a factor of 4^4, or 256.
//
// By what factor must we oversample to achieve a temperature resolution to
// the nearest hundredth of a degree C? In other words, "How may bits of
// resolution do we need to add?" The difference between 1 degrees C and
// 0.01 degrees C is a factor of 100 (100 is between 2^6 and 2^7, so we need
// somewhere between 6 and 7 more bits of resolution). Choosing '6 bits',
// we calculate our oversampling ratio to be 4^6, or 4096.
//
// A note about accuracy: oversampling and averaging provides a method to
// increase the 'resolution' of a measurement. The technique does nothing
// to improve a measurement's 'accuracy'. Just because we can measure a
// 0.01 degree change in temperature does not mean that the measurements
// are accurate to 0.01 degrees. Some possible sources of inaccuracies in
// this system are:
// 1. manufacturing tolerances in the temperature sensor itself (transfer
// characteristic variation)
// 2. VDD or VREF tolerance
// 3. ADC offset, gain, and linearity variations
// 4. Device self-heating
//
// Temperature Clock Function:
//
// The temperature clock maintains a record of days, hours, minutes, and
// seconds. The current time record is stored with the temperature value
// in each log entry. Clock updates are performed in the ADC end-of-conversion
// ISR at approximately once every second.
//
// Storage Function:
//
// MMC FLASH is used for storing the log entries. Each entry contains
// the temperature in hundredths of a degree C, the day, hour, minute, and
// second that the reading was taken. The LogUpdate function stores log
// entries in an external memory buffer and then writes that buffer out to the
// MMC when it is full. Communication with the MMC is performed through the
// MMC access functions. These functions provide transparent MMC access to
// the higher level functions (logging functions). The MMC interface is broken
// into two pieces. The high level piece consists of the user callable MMC
// access functions (MMC_FLASH_Read, MMC_FLASH_Write, MMC_FLASH_Clear,
// MMC_FLASH_MassErase). These functions are called by the user to execute
// data operations on the MMC. They break down the data operations into MMC
// commands. The low level piece consists of a single command execution
// function (MMC_Command_Exec) which is called by the MMC data manipulation
// functions. This function is called every time a command must be sent to the
// MMC. It handles all of the required SPI traffic between the Silicon Labs
// device and the MMC.
//
// Target: C8051F32x
// Tool chain: KEIL C51 6.03 / KEIL EVAL C51
//
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include <c8051f320.h> // SFR declarations
#include <stdio.h> // printf() and getchar()
#include <ctype.h> // tolower()
//-----------------------------------------------------------------------------
// 16-bit SFR Definitions for 'F32x
//-----------------------------------------------------------------------------
sfr16 DP = 0x82; // data pointer
sfr16 TMR2RL = 0xca; // Timer2 reload value
sfr16 TMR2 = 0xcc; // Timer2 counter
sfr16 PCA0CP1 = 0xe9; // PCA0 Module 1 Capture/Compare
sfr16 PCA0CP2 = 0xeb; // PCA0 Module 2 Capture/Compare
sfr16 PCA0 = 0xf9; // PCA0 counter
sfr16 PCA0CP0 = 0xfb; // PCA0 Module 0 Capture/Compare
sfr16 ADC0 = 0xbd; // ADC0 Data
//-----------------------------------------------------------------------------
// Global CONSTANTS
//-----------------------------------------------------------------------------
#define VERSION "1.0" // version identifier
#define TRUE 1
#define FALSE 0
#define START_SYSCLK 12000000
#define SYSCLK START_SYSCLK * 2 // SYSCLK frequency in Hz
#define BAUDRATE 115200 // Baud rate of UART in bps
#define SAMPLE_RATE 4096 // Sample frequency in Hz
#define INT_DEC 4096 // integrate and decimate ratio
#define FULL_SCALE 65536 // Full scale ADC0 value
#define PREC_FACTOR 1024 // This constant is used to preserve
// precision during temperature calc;
// VREF offset constant used (.01 mV)
#define VREF 243000
// in conversion of ADC sample to temp
// value;
// Temp sensor offset constant used
#define V_OFFSET 77600
// in conversion of ADC sample to temp
// value (.01 mV);
#define TEMP_SLOPE 2.86 // Temp sensor slope constant used
// in conversion of ADC sample to temp
// value;
// Constants that define available card sizes, 8MB through 128MB
#define PS_8MB 8388608L
#define PS_16MB 16777216L
#define PS_32MB 33554432L
#define PS_64MB 67108864L
#define PS_128MB 134217728L
// Physical size in bytes of one MMC FLASH sector
#define PHYSICAL_BLOCK_SIZE 512
// Erase group size = 16 MMC FLASH sectors
#define PHYSICAL_GROUP_SIZE PHYSICAL_BLOCK_SIZE * 16
// Log table start address in MMC FLASH
#define LOG_ADDR 0x00000000
// Size in bytes for each log entry
#define LOG_ENTRY_SIZE sizeof(LOG_ENTRY)
#define BUFFER_ENTRIES 32
// Size of XRAM memory buffer that stores table entries
// before they are written to MMC
#define BUFFER_SIZE LOG_ENTRY_SIZE * BUFFER_ENTRIES
// Command table value definitions
// Used in the MMC_Command_Exec function to
// decode and execute MMC command requests
#define EMPTY 0
#define YES 1
#define NO 0
#define CMD 0
#define RD 1
#define WR 2
#define R1 0
#define R1b 1
#define R2 2
#define R3 3
// Start and stop data tokens for single and multiple
// block MMC data operations
#define START_SBR 0xFE
#define START_MBR 0xFE
#define START_SBW 0xFE
#define START_MBW 0xFC
#define STOP_MBW 0xFD
// Mask for data response token after an MMC write
#define DATA_RESP_MASK 0x11
// Mask for busy token in R1b response
#define BUSY_BIT 0x80
// Command Table Index Constants:
// Definitions for each table entry in the command table.
// These allow the MMC_Command_Exec function to be called with a
// meaningful parameter rather than a number.
#define GO_IDLE_STATE 0
#define SEND_OP_COND 1
#define SEND_CSD 2
#define SEND_CID 3
#define STOP_TRANSMISSION 4
#define SEND_STATUS 5
#define SET_BLOCKLEN 6
#define READ_SINGLE_BLOCK 7
#define READ_MULTIPLE_BLOCK 8
#define WRITE_BLOCK 9
#define WRITE_MULTIPLE_BLOCK 10
#define PROGRAM_CSD 11
#define SET_WRITE_PROT 12
#define CLR_WRITE_PROT 13
#define SEND_WRITE_PROT 14
#define TAG_SECTOR_START 15
#define TAG_SECTOR_END 16
#define UNTAG_SECTOR 17
#define TAG_ERASE_GROUP_START 18
#define TAG_ERASE_GROUP_END 19
#define UNTAG_ERASE_GROUP 20
#define ERASE 21
#define LOCK_UNLOCK 22
#define READ_OCR 23
#define CRC_ON_OFF 24
sbit LED = P2^2; // LED='1' means ON
sbit SW2 = P2^0; // SW2='0' means switch pressed
sbit TX0 = P0^4; // UART0 TX pin
sbit RX0 = P0^5; // UART0 RX pin
//-----------------------------------------------------------------------------
// UNIONs, STRUCTUREs, and ENUMs
//-----------------------------------------------------------------------------
typedef union LONG { // byte-addressable LONG
long l;
unsigned char b[4];
} LONG;
typedef union INT { // byte-addressable INT
int i;
unsigned char b[2];
} INT;
typedef union { // byte-addressable unsigned long
unsigned long l;
unsigned char b[4];
} ULONG;
typedef union { // byte-addressable unsigned int
unsigned int i;
unsigned char b[2];
} UINT;
typedef struct LOG_ENTRY { // (7 bytes per entry)
int wTemp; // temperature in hundredths of a
// degree
unsigned int uDay; // day of entry
unsigned char bHour; // hour of entry
unsigned char bMin; // minute of entry
unsigned char bSec; // second of entry
unsigned char pad; // dummy byte to ensure aligned access;
} LOG_ENTRY;
// The states listed below represent various phases of
// operation;
typedef enum STATE {
RESET, // Device reset has occurred;
RUNNING, // Data is being logged normally;
FINISHED, // Logging stopped, store buffer;
STOPPED // Logging completed, buffer stored;
} STATE;
// This structure defines entries into the command table;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -