📄 mmc_datalogger_eeprom.c
字号:
//-----------------------------------------------------------------------------
// MMC_DataLogger_EEPROM.c
//-----------------------------------------------------------------------------
// Copyright 2003 Silicon Laboratories
//
// AUTH: BW / JS / GV
// DATE: 8 MAR 04
//
// This software shows an example of a data logging application that maintains
// the log on an MMC card. In addition, this software uses an external EEPROM
// to buffer MMC data. This removes the need to buffer large amounts of data in
// on-chip external memory.
//
// 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 EEPROM 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 Cygnal device
// and the MMC. Communication between the EEPROM and the Cygnal device is
// performed using SMBus.
//
// 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 'F31x, 'F32x, 'F33x
//-----------------------------------------------------------------------------
sfr16 DP = 0x82; // data pointer
sfr16 TMR2RL = 0xca; // Timer2 reload value
sfr16 TMR2 = 0xcc; // Timer2 counter
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 TEMP_OFFSET 50900000L // Temp sensor offset constant used
// in conversion of ADC sample to temp
// value;
#define TEMP_SLOPE 187433L // Temp sensor slope constant used
// in conversion of ADC sample to temp
// value;
#define TEMP_VREF 2430 // VREF offset constant used
// in conversion of ADC sample to temp
// value;
#define EEPROM_SIZE 32768
#define EEPROM_PAGE_SIZE 64
// 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 0x0000
// Size in bytes for each log entry
#define LOG_ENTRY_SIZE sizeof(LOG_ENTRY)
// Size of EEPROM buffer that stores table entries
// before they are written to MMC.
#define BUFFER_SIZE LOG_ENTRY_SIZE * 10
// 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
// LOCAL_BLOCK is the start of an EEPROM buffer for incoming temperature data;
// When this buffer is full, the page is written out to the MMC and erased for
// new data;
#define LOCAL_BLOCK 0x1000
// SCRATCH_BLOCK is used by the high level MMC functions as temporary storage;
#define SCRATCH_BLOCK 0x0000
// SMBus Definitions
#define SMB_FREQUENCY 300000 // Target SCL clock rate
#define WRITE 0x00 // SMBus WRITE command
#define READ 0x01 // SMBus READ command
// Device addresses (7 bits, lsb is a don't care)
#define EEPROM_ADDR 0xA0 // Device address for slave target
// Note: This address is specified
// in the Microchip 24LC02B
// datasheet.
// SMBus Buffer Size
#define SMB_BUFF_SIZE 0x08 // Defines the maximum number of bytes
// that can be sent or received in a
// single transfer
// Status vector - top 4 bits only
#define SMB_MTSTA 0xE0 // (MT) start transmitted
#define SMB_MTDB 0xC0 // (MT) data byte transmitted
#define SMB_MRDB 0x80 // (MR) data byte received
// End status vector definition
//-----------------------------------------------------------------------------
// 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 UINT // byte-addressable unsigned int
{
unsigned int i;
unsigned char b[2];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -