标题:
C8051F020的spi源代码 SPI0_Master,Slave,SPI0_EEPROM_Polled_Mode
[打印本页]
作者:
y2000yt
时间:
2018-3-4 12:25
标题:
C8051F020的spi源代码 SPI0_Master,Slave,SPI0_EEPROM_Polled_Mode
0.png
(39 KB, 下载次数: 71)
下载附件
2018-3-4 23:04 上传
SPI0_EEPROM_Polled_Mode单片机源程序如下:
//-----------------------------------------------------------------------------
// F02x_SPI0_EEPROM_Polled_Mode.c
//-----------------------------------------------------------------------------
// 此程序由【达达电子工作】的 RJ 整理 我们对此无版权
// 关于此例程请参考 C8051F2xx中文版.pdf 的第 19 章:串行外设接口总线(SPI0)
//
// Copyright 2006 Silicon Laboratories, Inc.
//
// Program Description:
//
// This program accesses a SPI EEPROM using polled mode access. The 'F02x MCU
// is configured in 4-wire Single Master Mode, and the EEPROM is the only
// slave device connected to the SPI bus. The read/write operations are
// tailored to access a Microchip 4 kB EEPROM 25LC320. The relevant hardware
// connections of the 'F02x MCU are shown here:
//
// P0.0 - UART TXD (digital output, push-pull)
// P0.1 - UART RXD (digital input, open-drain)
// P0.2 - SPI SCK (digital output, push-pull)
// P0.3 - SPI MISO (digital input, open-drain)
// P0.4 - SPI MOSI (digital output, push-pull)
// P0.5 - SPI NSS (digital input, open-drain) (unused in single master mode)
// P0.6 - GPIO (NSS) (digital output, push-pull) (used as slave select output)
// P1.6 - LED (digital output, push-pull)
//
// External crystal - 22.1184 MHz
//
// How To Test:
//
// Method1:
// 1) Download the code to a 'F02x device that is connected as above.
// 2) Run the code. The LED will blink fast during the write/read/verify
// operations.
// 3) If the verification passes, the LED will blink slowly. If it fails,
// the LED will be OFF.
//
// Method2 (optional):
// 1) Download code to a 'F02x device that is connected as above, and
// also connected to a RS232 transceiver.
// 2) Connect a straight serial cable from the RS232 transceiver to a PC.
// 3) On the PC, open HyperTerminal (or any other terminal program) and connect
// to the COM port at <BAUDRATE> and 8-N-1.
// 4) HyperTerminal will print the progress of the write/read operation, and in
// the end will print the test result as pass or fail. Additionally, if the
// verification passes, the LED will blink slowly. If it fails, the LED will
// be OFF.
//
//
// Target: C8051F02x
// Tool chain: Keil C51 7.50 / Keil EVAL C51
// Command Line: None
//
// Release 1.0
// -Initial Revision (PKC)
// -31 MAY 2006
//
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include <C8051F020.h> // SFR declarations
#include <stdio.h> // printf is declared here
//-----------------------------------------------------------------------------
// 16-bit SFR Definitions for the 'F02x
//-----------------------------------------------------------------------------
sfr16 TMR2 = 0xCC; // Timer2 low and high bytes together
//-----------------------------------------------------------------------------
// User-defined types, structures, unions etc
//-----------------------------------------------------------------------------
#ifndef BYTE
#define BYTE unsigned char
#endif
#ifndef UINT
#define UINT unsigned int
#endif
//-----------------------------------------------------------------------------
// Global Constants
//-----------------------------------------------------------------------------
#define SYSCLK 22118400 // External crystal frequency in Hz
#define BAUDRATE 115200 // Baud rate of UART in bps
// Microchip 25AA320 Slave EEPROM Parameters
#define F_SCK_MAX 2000000 // Max SCK freq (Hz)
#define T_NSS_DISABLE_MIN 500 // Min NSS disable time (ns)
#define EEPROM_CAPACITY 4096 // EEPROM capacity (bytes)
// EEPROM Instruction Set
#define EEPROM_CMD_READ 0x03 // Read Command
#define EEPROM_CMD_WRITE 0x02 // Write Command
#define EEPROM_CMD_WRDI 0x04 // Reset Write Enable Latch Command
#define EEPROM_CMD_WREN 0x06 // Set Write Enable Latch Command
#define EEPROM_CMD_RDSR 0x05 // Read Status Register Command
#define EEPROM_CMD_WRSR 0x01 // Write Status Register Command
sbit LED = P1^6; // LED='1' means ON
sbit EEPROM_CS = P0^6; // Active low chip select for EEPROM
//-----------------------------------------------------------------------------
// Function Prototypes
//-----------------------------------------------------------------------------
void Reset_Sources_Init (void);
void OSCILLATOR_Init (void);
void PORT_Init (void);
void TIMER2_Init (void);
void UART0_Init (void);
void SPI0_Init (void);
void Init_Device (void);
void Delay_us (BYTE time_us);
void Delay_ms (BYTE time_ms);
void EEPROM_Write (UINT address, BYTE value);
BYTE EEPROM_Read (UINT address);
//-----------------------------------------------------------------------------
// main() Routine
//-----------------------------------------------------------------------------
void main (void)
{
UINT address; // EEPROM address
BYTE test_byte; // Used as a temporary variable
Init_Device (); // Initializes hardware peripherals
// The following code will test the EEPROM by performing write/read/verify
// operations. The first test will write 0xFFs to the EEPROM, and the
// second test will write the LSBs of the EEPROM addresses.
// Fill EEPROM with 0xFF's
LED = 1;
printf("Filling with 0xFF's...\n");
for (address = 0; address < EEPROM_CAPACITY; address++)
{
test_byte = 0xFF;
EEPROM_Write (address, test_byte);
// Print status to UART0
if ((address % 16) == 0)
{
printf ("\nWriting 0x%04x: %02x ", address, (UINT)test_byte);
LED = ~LED;
}
else
printf ("%02x ", (UINT)test_byte);
}
// Verify EEPROM with 0xFF's
printf("\n\nVerifying 0xFF's...\n");
for (address = 0; address < EEPROM_CAPACITY; address++)
{
test_byte = EEPROM_Read (address);
// Print status to UART0
if ((address % 16) == 0)
{
printf ("\nVerifying 0x%04x: %02x ", address, (UINT)test_byte);
LED = ~LED;
}
else
printf ("%02x ", (UINT)test_byte);
if (test_byte != 0xFF)
{
LED = 0;
printf ("Error at %u\n", address);
while (1); // Stop here on error (for debugging)
}
}
// Fill EEPROM with LSB of EEPROM addresses
printf("\n\nFilling with LSB of EEPROM addresses...\n");
for (address = 0; address < EEPROM_CAPACITY; address++)
{
test_byte = address & 0xFF;
EEPROM_Write (address, test_byte);
// Print status to UART0
if ((address % 16) == 0)
{
printf ("\nWriting 0x%04x: %02x ", address, (UINT)test_byte);
LED = ~LED;
}
else
printf ("%02x ", (UINT)test_byte);
}
// Verify EEPROM with LSB of EEPROM addresses
printf("\n\nVerifying LSB of EEPROM addresses...\n");
for (address = 0; address < EEPROM_CAPACITY; address++)
{
test_byte = EEPROM_Read (address);
// print status to UART0
if ((address % 16) == 0)
{
printf ("\nVerifying 0x%04x: %02x ", address, (UINT)test_byte);
LED = ~LED;
}
else
printf ("%02x ", (UINT)test_byte);
if (test_byte != (address & 0xFF))
{
LED = 0;
printf ("Error at %u\n", address);
while (1); // Stop here on error (for debugging)
}
}
printf ("\n\nVerification success!\n");
while (1) // Loop forever
{
LED = ~LED; // Flash LED when done (all verified)
Delay_ms (200);
}
}
//-----------------------------------------------------------------------------
// Initialization Subroutines
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// PCA0_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// This function disables the watchdog timer.
//
//-----------------------------------------------------------------------------
void Reset_Sources_Init (void)
{
WDTCN = 0xDE; // Disable WDT
WDTCN = 0xAD;
}
//-----------------------------------------------------------------------------
// OSCILLATOR_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// This function initializes the system clock to use the external crystal
// at 22.1184 MHz.
//
//-----------------------------------------------------------------------------
void OSCILLATOR_Init (void)
{
int i = 0;
OSCXCN = 0x67;
for (i = 0; i < 3000; i++); // Wait 1ms for initialization
while ((OSCXCN & 0x80) == 0);
OSCICN = 0x0B;
}
//-----------------------------------------------------------------------------
// PORT_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// This function configures the crossbar and GPIO ports.
//
// P0.0 - TX0 (UART0), Push-Pull, Digital
// P0.1 - RX0 (UART0), Open-Drain, Digital
// P0.2 - SCK (SPI0), Push-Pull, Digital
// P0.3 - MISO (SPI0), Open-Drain, Digital
// P0.4 - MOSI (SPI0), Push-Pull, Digital
// P0.5 - NSS (SPI0), Open-Drain, Digital (Not used in single master mode)
// P0.6 - Unassigned, Push-Pull, Digital (Used as NSS slave select output)
// P0.7 - Unassigned, Open-Drain, Digital
// P1.0 - Unassigned, Open-Drain, Digital
// P1.1 - Unassigned, Open-Drain, Digital
// P1.2 - Unassigned, Open-Drain, Digital
// P1.3 - Unassigned, Open-Drain, Digital
// P1.4 - Unassigned, Open-Drain, Digital
// P1.5 - Unassigned, Open-Drain, Digital
// P1.6 - Unassigned, Push-Pull, Digital (LED D3 - Target Board)
// P1.7 - Unassigned, Open-Drain, Digital
// P2.0 - Unassigned, Open-Drain, Digital
// P2.1 - Unassigned, Open-Drain, Digital
// P2.2 - Unassigned, Open-Drain, Digital
// P2.3 - Unassigned, Open-Drain, Digital
// P2.4 - Unassigned, Open-Drain, Digital
// P2.5 - Unassigned, Open-Drain, Digital
// P2.6 - Unassigned, Open-Drain, Digital
// P2.7 - Unassigned, Open-Drain, Digital
// P3.0 - Unassigned, Open-Drain, Digital
// P3.1 - Unassigned, Open-Drain, Digital
// P3.2 - Unassigned, Open-Drain, Digital
// P3.3 - Unassigned, Open-Drain, Digital
// P3.4 - Unassigned, Open-Drain, Digital
// P3.5 - Unassigned, Open-Drain, Digital
// P3.6 - Unassigned, Open-Drain, Digital
// P3.7 - Unassigned, Open-Drain, Digital (Switch SW2 - Target Board)
//
//-----------------------------------------------------------------------------
void PORT_Init (void)
{
P0MDOUT = 0x55;
P1MDOUT = 0x40;
XBR0 = 0x06;
XBR2 = 0x40;
}
//-----------------------------------------------------------------------------
// TIMER2_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Initializes Timer2 to be clocked by SYSCLK for use as a delay timer.
//
//-----------------------------------------------------------------------------
void TIMER2_Init (void)
{
CKCON |= 0x20;
}
//-----------------------------------------------------------------------------
// UART0_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Configures the UART0 using Timer1, for <BAUDRATE> and 8-N-1. Once this is
// set up, the standard printf function can be used to output data.
//
//-----------------------------------------------------------------------------
void UART0_Init (void)
{
TMOD = 0x20; // TMOD: timer 1, mode 2, 8-bit reload
TH1 = -(SYSCLK/BAUDRATE/16); // set Timer1 reload value for baudrate
TL1 = TH1; // set Timer1 initial value
CKCON |= 0x10; // Timer1 uses SYSCLK as time base
PCON |= 0x80; // SMOD0 = 1
TR1 = 1; // start Timer1
SCON0 = 0x50; // UART mode 1, 8-bit UART, enable RX
TI0 = 1; // Indicate TX0 ready
}
//-----------------------------------------------------------------------------
// SPI0_Init
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Configures SPI0 to use 4-wire Single-Master mode. The SPI timing is
// configured for Mode 0,0 (data centered on first edge of clock phase and
// SCK line low in idle state). The SPI clock is set to 1.6 MHz (nominal).
// The slave select pin is set to 1.
//
//-----------------------------------------------------------------------------
void SPI0_Init()
{
SPI0CFG = 0x07; // Data sampled on 1st SCK rising edge
// 8-bit data words
SPI0CN = 0x03; // Master mode; SPI enabled; flags
// cleared
// Note: This example uses the external crystal as SYSCLK.
// The equation for SPI0CKR is (SYSCLK/(2*F_SCK_MAX))-1, but this yields
// a SPI frequency that is slightly more than 2 MHz. But, 2 MHz is the max
// frequency spec of the EEPROM used here. So, the "-1" term is omitted
// in the following usage:
SPI0CKR = (SYSCLK/(2*F_SCK_MAX));
EEPROM_CS = 1; // Deactivate Slave Select
}
//-----------------------------------------------------------------------------
// Init_Device
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : None
//
// Calls all device initialization functions.
//
//-----------------------------------------------------------------------------
void Init_Device (void)
{
Reset_Sources_Init ();
OSCILLATOR_Init ();
PORT_Init ();
TIMER2_Init ();
UART0_Init ();
SPI0_Init ();
}
//-----------------------------------------------------------------------------
// Support Subroutines
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Delay_us
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : 1. time_us - time delay in microseconds
// range: 1 to 255
//
// Creates a delay for the specified time (in microseconds) using TIMER2. The
// time tolerance is approximately +/-50 ns (1/SYSCLK + function call time).
//
//-----------------------------------------------------------------------------
void Delay_us (BYTE time_us)
{
TR2 = 0; // Stop timer
TF2 = 0; // Clear timer overflow flag
TMR2 = -( (UINT)(SYSCLK/1000000) * (UINT)(time_us) );
TR2 = 1; // Start timer
while (!TF2); // Wait till timer overflow occurs
TR2 = 0; // Stop timer
}
//-----------------------------------------------------------------------------
// Delay_ms
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : 1. time_ms - time delay in milliseconds
// range: 1 to 255
//
// Creates a delay for the specified time (in milliseconds) using TIMER2. The
// time tolerance is approximately +/-50 ns (1/SYSCLK + function call time).
//
//-----------------------------------------------------------------------------
void Delay_ms (BYTE time_ms)
{
BYTE i;
while(time_ms--)
for(i = 0; i< 10; i++) // 10 * 100 microsecond delay
Delay_us (100);
}
//-----------------------------------------------------------------------------
// EEPROM_Write
//-----------------------------------------------------------------------------
//
// Return Value : None
// Parameters : 1. address - the destination EEPROM address.
// range: 0 to EEPROM_CAPACITY
// 2. value - the value to write.
// range: 0x00 to 0xFF
//
// Writes one byte to the specified address in the EEPROM. This function polls
// the EEPROM status register after the write operation, and returns only after
// the status register indicates that the write cycle is complete. This is to
// prevent from having to check the status register before a read operation.
//
//-----------------------------------------------------------------------------
void EEPROM_Write (UINT address, BYTE value)
{
// Writing a byte to the EEPROM is a five-step operation.
// Step1: Set the Write Enable Latch to 1
EEPROM_CS = 0; // Step1.1: Activate Slave Select
SPI0DAT = EEPROM_CMD_WREN; // Step1.2: Send the WREN command
while (!SPIF); // Step1.3: Wait for end of transfer
SPIF = 0; // Step1.4: Clear the SPI intr. flag
EEPROM_CS = 1; // Step1.5: Deactivate Slave Select
Delay_us (1); // Step1.6: Wait for at least
// T_NSS_DISABLE_MIN
// Step2: Send the WRITE command
EEPROM_CS = 0;
SPI0DAT = EEPROM_CMD_WRITE;
while (!SPIF);
SPIF = 0;
// Step3: Send the EEPROM destination address (MSB first)
SPI0DAT = (BYTE)((address >> 8) & 0x00FF);
while (!SPIF);
SPIF = 0;
SPI0DAT = (BYTE)(address & 0x00FF);
while (!SPIF);
SPIF = 0;
// Step4: Send the value to write
SPI0DAT = value;
while (!SPIF);
SPIF = 0;
EEPROM_CS = 1;
Delay_us (1);
……………………
…………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
SPI.zip
(85.69 KB, 下载次数: 15)
2018-3-4 12:24 上传
点击文件名下载附件
51F020
下载积分: 黑币 -5
作者:
rzh98
时间:
2020-4-16 19:34
请问这个可以用来读SD卡吗
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1