您好,
请问是否有MSP430读写SPI接口EEPROM的参考例程?
谢谢。
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
//文件名:MC430F14_DEMO_4.c
//版本: 1.0
//描述:MC430F14开发板的主程序,MSP430模拟SPI接口与AT93C46读写实例。
// 向AT93C46写入一个数据,然后读出一个数据进行验证。
//编程环境:IAR WE430 3.40A
//编写: www.microcontrol.cn DC
//时期: 2006.9.20.
#include <msp430x14x.h>
#include "MC430F14_DEMO_4.h"
void init(void);
//-----------------------------------------------------
void init(void)
{ unsigned int i;
P5DIR |= 0x01 ; //5.0(93C46_CS)为输出
P5DIR |= 0x02 ; //5.1(93C46_DI)为输出
P5DIR |= 0x08 ; //5.3(93C46_SCLK)为输出
P1DIR |= BIT1; //P1.0(LED)指示数据正确性
P1OUT |= BIT1; //先关闭LED
BCSCTL1 &= ~XT2OFF; //启动XT2,
do
{IFG1 &= ~OFIFG; //清OSCFault标志
for(i=0xFF;i>0;i--); //延时等待
}
while((IFG1 & OFIFG) != 0); //查OSCFault,为0时转换完成
BCSCTL2 |= SELM_3+SELM1; //MCLK 8分频,MCLK为XT2
}
void main(void)
{unsigned char ErrorFlag; //错误标志位
unsigned int i;
WDTCTL = WDTPW + WDTHOLD; // 停止WDT
init();
i=0;
ErrorFlag = Write_One(0x00,0x0f);
i = Read_One(0x00);
if (i==0x0f)
P1OUT ^= BIT1;
LPM0;
}
//文件名:MC430F14_DEMO_4.h
//版本: 1.0
//描述:程序声明
//编程环境:IAR WE430 3.40A
//编写: www.microcontrol.cn DC
//时期: 2006.9.20.
//***********************************************************************
//*Name :READ()
//*Discription :93C46的字读取程序
//*输入:要读取的字地址(8bit:7位,16bit:6位)
//*输出:读取的字数值
//*从指定单元读出数据命令
//**********************************************************************
unsigned int Read_One(unsigned char Address);
//**********************************************************************
//*Name :WRITE()
//*Discription :93C46的字写入程序
//*输入: address 要写入的字地址(6位)
//* op_data 要写入的数据(16位)
//*输出: 读取的字数值
//*写入指定单元命令
//**********************************************************************
unsigned int Write_One(unsigned char Address,unsigned int Op_Data);
//文件名:MSP430_93C46.c
//版本: 1.0
//描述:MC430F14开发板的主程序,MSP430模拟SPI接口与AT93C46操作主程。
//以下AT93C46操作程序中是参考Benny Chen先生的例程。
//编程环境:IAR WE430 3.40A
//编写: www.microcontrol.cn Benny Chen & DC
//时期: 2006.9.20.
#define CS_93C46_LOW P5OUT &= ~0x01 // CS = 0
#define CS_93C46_HIGH P5OUT |= 0x01 // CS = 1
#define SK_93C46_LOW P5OUT &= ~0x08 // SK = 0
#define SK_93C46_HIGH P5OUT |= 0x08 // SK = 1
#define DO_93C46_LOW ~(P5IN & 0x04) // DO = 0 从93C46输出0
#define DO_93C46_HIGH P5IN & 0x04 // DO = 1 从93C46输出1
#define DI_93C46_LOW P5OUT &= ~0x02 // DI = 0
#define DI_93C46_HIGH P5OUT |= 0x02 // DI = 1
#define CMD_DisWrite 0x00 //禁止写命令
#define CMD_WriteAll 0x20 // x020:8bit 0x10:16bit, 写全部命令
#define CMD_EraseAll 0x40 // x040:8bit 0x20:16bit, 擦全部命令
#define CMD_EnWrite 0x60 //0x60:8bit 0X30:16BIT 允许写命令
#define CMD_Write 0x80 //8bit:0X80(0 1A6A5A4 A3A2A1A0) 16bit:0X40(01A5A4 A3A2A1A0)
#define CMD_Read 0x100 //8bit:0X100(10A6A5A4 A3A2A1A0) 16bit:0X80(10A5A4 A3A2A1A0)
#define CMD_Erase 0x180 //8bit:0X180(1 1A6A5A4 A3A2A1A0) 16bit:0XC0(11A5A4 A3A2A1A0)
#define START_Bit 0x200 //8bit:0x200 16bit:0x100
/*************************************************************/
/*Name : Delay() */
/*Discription : 延时子程序/
/*************************************************************/
void Delay(unsigned int num)
{
while(--num);
}
/*************************************************************/
/*Name : START_93C46() */
/*Discription : 启动93C46 */
/*************************************************************/
void START_93C46()
{
CS_93C46_HIGH; /*开启93C46*/
CS_93C46_LOW;
DI_93C46_LOW;
SK_93C46_LOW;
CS_93C46_HIGH; //CS片选高电平有效
Delay(1000);
}
/****************************************************************/
/*Name :END_93C46() */
/*Discription :用于93C46的结束
/****************************************************************/
void END_93C46()
{
CS_93C46_LOW; //CS片选高电平无效
DI_93C46_HIGH;
SK_93C46_HIGH;
}
/*************************************************************/
/*Name :SEND_DATA_93C46() */
/*Discription :在93C46启动下,送入指定位数的数据 */
/*输入: op_data 要输入的数据 */
/* num 输入的位数 */
/* 最高位先送出 */
/*************************************************************/
void SEND_DATA_93C46(unsigned int Op_Data,unsigned char Num)
{
unsigned char i;
Op_Data = Op_Data << (16 - Num); /*左移去掉无用位*/
for(i = Num; i > 0; i --)
{
if ((Op_Data & 0X8000) ==0 )
DI_93C46_LOW; //MCU输出1位0
else
DI_93C46_HIGH; //MCU输出1位1
SK_93C46_HIGH; //产生一个时钟
SK_93C46_LOW;
Op_Data <<= 1; //指向下一位
}
}
/*********************************************************/
/*Name : EWEN_93C46() */
/*Discription :93C46的编程启动.操作码(100 11XXXXX) */
/* 擦写指定单元命令 */
/*********************************************************/
void EWEN_93C46()
{
START_93C46();
SEND_DATA_93C46(START_Bit + CMD_EnWrite, 0X0A);
END_93C46();
}
/***********************************************************************/
/*Name : EWDS_93C46() */
/*Discription : 93C46的编程关闭.操作码(8bit:100 00XXXXX 16bit:100 00XXXX) */
/*擦写禁止命令 */
/**********************************************************************/
void EWDS_93C46()
{
START_93C46();
SEND_DATA_93C46(START_Bit + CMD_DisWrite, 0X0A);
END_93C46();
}
/***********************************************************************/
/*Name :READ() */
/*Discription :93C46的字读取程序 */
/*输入:要读取的字地址(8bit:7位,16bit:6位) */
/*输出:读取的字数值 */
/*从指定单元读出数据命令 */
/**********************************************************************/
unsigned int Read_One(unsigned char Address)
{
unsigned int i;
unsigned int Result;
START_93C46(); //启动93C46
SEND_DATA_93C46(START_Bit + CMD_Read + Address, 0X0A);
Result = 0; //存放返回数据的缓冲先清零
for(i =8; i >0; i--) //循环读出8个数据
{
Result = Result << 1; //先读最高位
SK_93C46_HIGH;
SK_93C46_LOW;
if (DO_93C46_HIGH)
Result = Result | 0X01;
}
END_93C46(); //结束93C46
return Result; //返回读出的数据
}
/**********************************************************************/
/*Name :WRITE() */
/*Discription :93C46的字写入程序 */
/*输入: address 要写入的字地址(6位) */
/* op_data 要写入的数据(16位) */
/*输出: 读取的字数值 */
/*写入指定单元命令 */
/**********************************************************************/
unsigned int Write_One(unsigned char Address,unsigned int Op_Data)
{
unsigned char ErrorFlag; //错误标志位
unsigned int mCount;
EWEN_93C46(); //启动93C46
START_93C46(); //擦写指定单元命令
SEND_DATA_93C46(START_Bit + CMD_Write + Address, 0x0A); //写入指定单元命令
SEND_DATA_93C46(Op_Data,0X08); //接着写入指定单元命令的数据
CS_93C46_LOW;
CS_93C46_HIGH;
ErrorFlag = 0; //清错误标志位
mCount = 50000; //延时时间
while (DO_93C46_LOW) //擦写忙闲标志
{
if (! --mCount)
{
ErrorFlag = 1; //延时过,还在忙则表示有错识
break;
}
}
END_93C46(); //结束93C46
EWDS_93C46(); //擦写禁止命令
return ErrorFlag; //返回表示擦除状态的特征
}
其实给你参考代码意义不大,你还是需要自己去根据EEPROM写一个SPI的程序,不如查看TI的一些SPI的code example能够帮助到你理解。下面是一个EEPROM的例程。
#include <MSP430Fx.h>
#include "dispport.h"
#include "spi_eeprom.h"
unsigned char EE_JustWritten=0; // Set to TRUE to force WaitRdy check before read.
void EE_Select(void) { P5OUT&=~EE_CS; }
void EE_DeSelect(void) { P5OUT|=EE_CS; }
unsigned char EE_RW(unsigned char txbyte) {
// Writes one byte to bitbang SPI, msb first, while receiving a byte
// EEprom is assumed to be faster than the processor in bitbang mode
unsigned char rxbyte=0;
char i;
for (i=0;i=7;i++) {
if (txbyte & 0x80) P5OUT|=EE_SI; else P5OUT&=~EE_SI; // set data
P5OUT|=EE_CK; // Clock data in
rxbyte<=1; // Rotate a nice hole for the data
if (P5IN & EE_SO) rxbyte++;
P5OUT&=~EE_CK; // And get a bit out
txbyte<=1;
}
return rxbyte;
}
void EE_WREN(void) { EE_Select(); EE_RW(0x06); EE_DeSelect(); } // WREN command
void EE_WRDI(void) { EE_Select(); EE_RW(0x04); EE_DeSelect(); } // WRDI command
unsigned char EE_RDSR(void) { // Read SR
// SR is xxxx BP1 BP0 WEN -RDY
unsigned int res;
EE_Select(); EE_RW(0x05); res=EE_RW(0); EE_DeSelect();
return res;
}
void EE_WRSR(unsigned char status) { // Read SR
EE_Select(); EE_RW(0x01); EE_RW(status); EE_DeSelect();
}
void EE_WaitRdy(void) {
while (EE_RDSR() & 1) {}; // Loop until -RDY drops to 0
EE_JustWritten=0;
}
unsigned char EE_WR(unsigned int adr, unsigned char data) {
// Write a byte to the EEPROM. Returns status register on completion.
if (EE_JustWritten) EE_WaitRdy(); // See if we were finished with the last one
EE_WREN(); // Enable Write
EE_Select(); EE_RW(0x02); // Write command
EE_RW(adr >> 8); EE_RW(adr & 0xFF); // send address
EE_RW(data);
EE_DeSelect();
EE_JustWritten=1;
return EE_RDSR();
}
unsigned char EE_RD(unsigned int adr) {
// Read a byte from the EEPROM
unsigned int res;
if (EE_JustWritten) EE_WaitRdy();
EE_Select(); EE_RW(0x03); // Read command
EE_RW(adr >> 8); EE_RW(adr & 0xFF); // send address
res=EE_RW(0);
EE_DeSelect();
return res;
}
unsigned char EE_Write(unsigned int adr, unsigned char *data, unsigned char datalen) {
// Writes up to 64 bytes to the EEPROM. Returns status register on completion.
unsigned char i;
if (EE_JustWritten) EE_WaitRdy(); // See if we were finished with the last one
EE_WREN(); // Enable Write
EE_Select(); EE_RW(0x02); // Write command
EE_RW(adr >> 8); EE_RW(adr & 0xFF); // send address
for (i=0;i<datalen;i++) EE_RW(*data++);
EE_DeSelect();
EE_JustWritten=1;
return EE_RDSR();
}
void EE_Read(unsigned int adr, unsigned char *data, unsigned int datalen) {
// Reads any number of bytes from the EEPROM
unsigned int i;
if (EE_JustWritten) EE_WaitRdy();
EE_Select(); EE_RW(0x03); // Read command
EE_RW(adr >> 8); EE_RW(adr & 0xFF); // send address
for (i=0;i<datalen;i++) *data++=EE_RW(0);
EE_DeSelect();
}