最近因为用到了MSP430F149这个芯片,其中硬件已经设计好了,串口1和SPI1都要用,但大家都知道MSP430F149的这两个外设共用一些寄存器,两个同时用就很麻烦,所以这里我们模拟一个SPI来用, 先简单讲一下FM25CL640, FM25CL640支持SPI模式0和3,我们这里用的模式3,详细FM25CL640资料大家可以再去百度一下。
首先是SPI引脚的初始化:
void Master_SPI_Init(void)
{
P5DIR |= BIT0+BIT1+BIT3;
P5DIR &=~BIT2;
P5OUT |= BIT0+BIT1+BIT3;
}
在这里用芯片的SPI1的接口(用其他IO一样的),MSP430F149,IO的方向是通过寄存器PxDIR来配置的,0是是输入,1是输出; 一组IO口有8个 P5.0到P5.7对应0到第7位。这里: P5.0CS是片选信号,方向输出 P5.1MOSI,这个口是主机输出,从机输入,放向输出 P5.2MISO,这个口是主机输入,从机输出,放向输入 P5.3SCK,这个口是时钟信号,方向输出, 同时为了方便我们这里需要做一些定义:
#define SPI_SC_H (P5OUT |=BIT0)
#define SPI_SC_L (P5OUT &=~BIT0)
#define SPI_CLK_H (P5OUT |=BIT3)
#define SPI_CLK_L (P5OUT &=~BIT3)
#define SPI_MOSI_H (P5OUT |=BIT1)
#define SPI_MOSI_L (P5OUT &=~BIT1)
#define SPI_MISO (P5IN&0X04)
#define uchar unsigned char
#define uint unsigned int
MSP430F149,IO口的输出寄存器是PxOUT,输入寄存器是PxIN,比如说将P5.0输出高电平,那么就把P5OUT的第0位置1,还有比如要读P5.3输入的电平,那么就去查看P5IN的第3位,上面的BIT0是为了方便使用将数字封装了下,是官方头文件里面提供的, 接下来我们先写发送一字节的函数,
void Spisend(uchar dataR)
{
for (int i=0; i<8; ++i)
{
SPI_CLK_L;
if (dataR & 0x80)
{
SPI_MOSI_H ;
}
else
{
SPI_MOSI_L ;
}
SPI_CLK_H;
dataR<<=1;
}
}
接下来写往指定的地址写指定长度的数据
void SPI_write_FM25CL64(uint address,uchar * buffer, uchar len)
{
uchar addr_tempH,addr_tempL;
addr_tempH=(address&0xff00)>>8;
addr_tempL=address&0x00ff;
SPI_SC_L ;
Spisend(FM25CL64Wren_CMD);
SPI_SC_H ;
SPI_SC_L ;
Spisend(FM25CL64Write_CMD);
Spisend(addr_tempH);
Spisend(addr_tempL);
for( uchar i = 0; i < len; i++ )
{
Spisend(buffer[i]);
}
SPI_SC_H ;
}
这里需要注意FM25CL64在写之前需要使能一下,其命令码如下:
#define FM25CL64Read_CMD 0x03
#define FM25CL64Write_CMD 0x02
#define FM25CL64Wren_CMD 0x06
#define FM25CL64Wrdi_CMD 0x04
#define FM25CL64Rdsr_CMD 0x05
#define FM25CL64Wrsr_CMD 0x01
需要注意的这里先将片选拉低使能,然后发送写使能,发完后需要先将片选拉高,然后再次拉低开始下面的内容,我起先是一开始拉低片选直到操作完所有在拉高,结果弄了半天没写进去。操作完写使能,再次拉低片选,发写命令,然后发送地址,先发高8位再发低8位,然后写数据,我们这里用一个for循环,地址会自己递增我们不用管。写完将片选拉高就行。 接下来是读数据,先写读一个字节的
uchar Spireceive(void)
{
uchar data = 0x00;
for (int i=0; i<8; ++i)
{
SPI_CLK_L;
if(SPI_MISO)
{
data<<=1;
data +=1;
}
else
{
data<<=1;
}
SPI_CLK_H;
}
return (data);
}
接下来写从指定的地址读取指定长度的数据
uchar SPI_read_FM25CL64(uint address,uchar * buffer ,uchar len)
{
uchar data_temp,addr_tempH,addr_tempL;
addr_tempH=(address&0xff00)>>8;
addr_tempL=address&0x00ff;
SPI_SC_L ;
Spisend(FM25CL64Read_CMD);
Spisend(addr_tempH);
Spisend(addr_tempL);
for( uchar i = 0; i < len; i++ )
{
buffer[ i ] = Spireceive();
}
SPI_SC_H ;
return data_temp;
}
这里读不需要使能,直接发读命令然后地址(先高8位在低8位),然后循环读数据,同样地址不用管会自己递增。 这样我们的收发就写好了,然后去试试,
unsigned char TestBuff1[]={0X01,0X02,'3','4','5','6','A','B','C','D'};
unsigned char TestBuff[]={0,0,0,0,0,0,0,0,0,0};
void main(void)
{
P1DIR = 0X00;P1OUT = 0X00;
P2DIR = 0X00;P2OUT = 0X00;
P3DIR = 0X00;P3OUT = 0x00;
P4DIR = 0X00;P4OUT = 0X00;
P5DIR = 0X00;P5OUT = 0X00;
P6DIR = 0X00;P6OUT = 0X00;
WDTCTL = WDTPW + WDTHOLD;
BCSCTL1 &= ~XT2OFF;
do
{
IFG1 &= ~OFIFG;
for (z = 0xFF; z > 0; z--);
}
while ((IFG1 & OFIFG));
BCSCTL2 |= SELM_2 + SELS;
Master_SPI_Init();
SPI_write_FM25CL64( 0x0001, TestBuff1, 10);
SPI_read_FM25CL64( 0x0001, TestBuff, 10 );
while(1)
{
}
}
我们将TestBuff1数组的内容写进去,然后读出来放到TestBuff,运行后:
|