当前位置:首页 > 单片机 > 单片机
[导读] 在学习过程中,发现一点容易被忽视而又很严重的问题---那就是关于SSP1的引脚使用P0[7]-P0[8]-P0[9]时,是W型IO配置。寄存器的第7位很容易被我们设置为0--但是手册上是要求必须为1,否则不能正常工作,这

在学习过程中,发现一点容易被忽视而又很严重的问题---那就是关于SSP1的引脚使用P0[7]-P0[8]-P0[9]时,是W型IO配置。寄存器的第7位很容易被我们设置为0--但是手册上是要求必须为1,否则不能正常工作,这里我走了一点弯路。



#include"ssp_lpc1788.h"


#define SPI_FLASH_PageSize 256 //页大小
#define SPI_FLASH_PerWritePageSize 256 //写页大小


/*----------------初始化SSP0-------------*/
void SSP0_Init(unsigned long sysClk, unsigned spiClk)
{
volatile uint32_t dummy;

dummy = dummy;

LPC_IOCON->P2_22 =0x22; // SSP0_SCK
LPC_IOCON->P2_26 =0x22; // SSP0_MISO
LPC_IOCON->P2_27 =0x22; // SSP0_MOSI

LPC_IOCON->P2_23=0x30; //SSP1_CS-直接普通上拉IO
LPC_GPIO2->DIR "= (1UL << 23); //输出
LPC_GPIO2->SET|=(1<<23);//置一

LPC_SC->PCONP |= (1UL << 21); //SSP0 时钟开启

LPC_SSP0->CR0 = 0x0007; // 8Bit, CPOL=0, CPHA=0
LPC_SSP0->CR1 = 0x0002; // SSP0-使能-主模式

LPC_SSP0->CPSR = sysClk/spiClk; //时钟预分频寄存器

while( LPC_SSP0->SR & ( 1 << 4 ) ); //忙

while( LPC_SSP0->SR & ( 1 << 2 ) ) //接收FIFO不为空
{
dummy = LPC_SSP0->DR; //假读取去清空FIFO
}

}

/*-------------SSP0-发送数据-----------------*/
void SSP0_WriteByte(unsigned char data)
{
uint8_t Dummy;

LPC_SSP0->DR = data; //载入要发送的数据
while (LPC_SSP0->SR & (1 << 4)){}//等待发送完成
Dummy=LPC_SSP0->DR; //假读取去清空FIFO
}

/*-------------SSP0-接收数据-----------------*/
uint8_t SSP0_RegisterByte(void)
{
LPC_SSP0->DR = 0xFF; //无效指令
while (LPC_SSP0->SR & (1 << 4)){}//忙等待

return (LPC_SSP0->DR); //接收数据
}


/*-----------------------------------SSP1--------------------------*/
/*----------------初始化SSP1-------------*/
void SSP1_Init(unsigned long sysClk, unsigned spiClk)
{
volatile uint32_t dummy;


LPC_IOCON->P0_7 =0xA2; // SSP1_SCK
LPC_IOCON->P0_8 =0xA2; // SSP1_MISO
LPC_IOCON->P0_9 =0xA2; // SSP1_MOSI

LPC_IOCON->P0_6=0x30; //SSP1_CS-普通上拉IO
LPC_GPIO0->DIR |= (1UL << 6); //输出
LPC_GPIO0->SET|=(1<<6);//置一

LPC_SC->PCONP |= (1UL << 10); //SSP1 时钟开启

LPC_SSP1->CR0 = 0x0007; // 8Bit, CPOL=0, CPHA=0
LPC_SSP1->CR1 = 0x0002; // SSP1-使能-主模式

LPC_SSP1->CPSR = sysClk/spiClk; //时钟预分频寄存器

while( LPC_SSP1->SR & ( 1 << 4 ) ); //忙

while( LPC_SSP1->SR & ( 1 << 2 ) ) //接收FIFO不为空
{
dummy = LPC_SSP1->DR; //假读取去清空FIFO
}
}

/*-------------SSP1-发送数据-----------------*/
void SSP1_WriteByte(unsigned char data)
{
uint8_t Dummy;

LPC_SSP1->DR = data; //载入要发送的数据
while (LPC_SSP1->SR & (1 << 4)){} //等待发送完成
Dummy=LPC_SSP1->DR; //假读取去清空FIFO
}

/*-------------SSP1-接收数据-----------------*/
uint8_t SSP1_RegisterByte(void)
{
LPC_SSP1->DR = 0xFF; //无效指令
while (LPC_SSP1->SR & (1 << 4)){} //忙等待

return (LPC_SSP1->DR); //接收数据
}


/*---------------------W25Q16---------------*/
//---------写使能---
void SSP_FLASH_WriteEnable(void)
{
FLASH_CS_LOW();
SSP0_WriteByte(0x06);
FLASH_CS_HIGH();
}
//--------等待写完成--
void SSP_FLASH_WaitForWriteEnd(void)
{
uint16_t i=2000;
uint8_t FLASH_Status = 0;

FLASH_CS_LOW();
SSP0_WriteByte(0x05);
do
{
FLASH_Status = SSP0_RegisterByte();
i--;
}
while (((FLASH_Status & 0x01) == 1)||(i==0));
FLASH_CS_HIGH();

}

/*----关于擦除---在写入数据之前必须保证被写入的位值是0xff---这就是擦除的作用*/

//-------------扇区擦除----------
void SSP_FLASH_SectorErase(uint32_t SectorAddr)
{
SSP_FLASH_WriteEnable();//写使能
SSP_FLASH_WaitForWriteEnd();//忙状态

FLASH_CS_LOW();//CS=0
SSP0_WriteByte(0x20);//0x20
SSP0_WriteByte((SectorAddr & 0xFF0000) >> 16);//擦除扇区起始地址
SSP0_WriteByte((SectorAddr & 0xFF00) >> 8);
SSP0_WriteByte(SectorAddr & 0xFF);
FLASH_CS_HIGH();//CS=1

SSP_FLASH_WaitForWriteEnd();//忙状态--等待擦除完成
}
//-----------块擦除-------
void SSP_FLASH_BlockErase(uint32_t BlockAddr)
{
BlockAddr*=65536;//0x010000
SSP_FLASH_WriteEnable();//写使能
SSP_FLASH_WaitForWriteEnd();

FLASH_CS_LOW();
SSP0_WriteByte(0xD8);//0xD8
SSP0_WriteByte((BlockAddr & 0xFF0000) >> 16);//擦除块起始地址
SSP0_WriteByte((BlockAddr & 0xFF00) >> 8);
SSP0_WriteByte(BlockAddr & 0xFF);
FLASH_CS_HIGH();

SSP_FLASH_WaitForWriteEnd();
}
//----------整片擦除--
void SSP_FLASH_BulkErase(void)
{
SSP_FLASH_WriteEnable(); //写使能

FLASH_CS_LOW();
SSP0_WriteByte(0xc7); //整片擦除
FLASH_CS_HIGH();

SSP_FLASH_WaitForWriteEnd();
}
//---------单页写入-----
void SSP_FLASH_PageWrite(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{
SSP_FLASH_WriteEnable();

FLASH_CS_LOW();
SSP0_WriteByte(0x02);//CMD2--0x02--------页写入
SSP0_WriteByte((WriteAddr & 0xFF0000) >> 16);//写入起始地址
SSP0_WriteByte((WriteAddr & 0xFF00) >> 8);
SSP0_WriteByte(WriteAddr & 0xFF);

if(NumByteToWrite > SSP_FLASH_PerWritePageSize) //写入数据多余页最大数据
NumByteToWrite = SSP_FLASH_PerWritePageSize;
while (NumByteToWrite--)
{
SSP0_WriteByte(*pBuffer); //写数据
pBuffer++;
}
FLASH_CS_HIGH();

SSP_FLASH_WaitForWriteEnd();
}
//--------多页写入---
void SSP_FLASH_BufferWrite(uint8_t* pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite)
{
uint8_t NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0, temp = 0;

Addr = WriteAddr % SSP_FLASH_PageSize; //首页地址
count = SSP_FLASH_PageSize - Addr;//首页要写入的数据个数
NumOfPage = NumByteToWrite / SSP_FLASH_PageSize;//页数
NumOfSingle = NumByteToWrite % SSP_FLASH_PageSize; //余数--最后一页不满一页个数

if (Addr == 0)
{
if (NumOfPage == 0) //只有一页
{
SSP_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite); //?±?óD′è?
}
else //多页
{
while (NumOfPage--) //写满页的数据
{
SSP_FLASH_PageWrite(pBuffer, WriteAddr, SSP_FLASH_PageSize);
WriteAddr += SSP_FLASH_PageSize;
pBuffer += SSP_FLASH_PageSize;
}

SSP_FLASH_PageWrite(pBuffer, WriteAddr, NumOfSingle);//写最后不满一页的数据
}
}
else
{
if (NumOfPage == 0)
{
if (NumOfSingle > count)
{
temp = NumOfSingle - count;
SSP_FLASH_PageWrite(pBuffer, WriteAddr, count);
WriteAddr += count;
pBuffer += count;

SSP_FLASH_PageWrite(pBuffer, WriteAddr, temp);
}
else
{
SSP_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite);
}
}
else
{
NumByteToWrite -= count;
NumOfPage = NumByteToWrite / SSP_FLASH_PageSize;
NumOfSingle = NumByteToWrite % SSP_FLASH_PageSize;

SSP_FLASH_PageWrite(pBuffer, WriteAddr, count);
WriteAddr += count;
pBuffer += count;

while (NumOfPage--)
{
SSP_FLASH_PageWrite(pBuffer, WriteAddr, SSP_FLASH_PageSize);
WriteAddr += SSP_FLASH_PageSize;
pBuffer += SSP_FLASH_PageSize;
}

if (NumOfSingle != 0)
{
SSP_FLASH_PageWrite(pBuffer, WriteAddr, NumOfSingle);
}
}
}
}
//--------读数据-----------
void SSP_FLASH_BufferRead(uint8_t* pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead)
{
FLASH_CS_LOW();
SSP0_WriteByte(0x03); //CMD3--0x03-----//读数据
SSP0_WriteByte((ReadAddr & 0xFF0000) >> 16);
SSP0_WriteByte((ReadAddr& 0xFF00) >> 8);
SSP0_WriteByte(ReadAddr & 0xFF);

while (NumByteToRead--)
{
*pBuffer = SSP0_RegisterByte();//读入到指定数组
pBuffer++;
}
FLASH_CS_HIGH();
}

/*-----------读取厂家ID------------*/
uint32_t SSP_FLASH_ReadID(void)
{
uint32_t temp1=0,temp2=0,temp3=0,temp=0;

LPC_GPIO0->CLR|=(1<<6); //CS=0

SSP1_WriteByte(0x9F); //读取ID指令
temp1 =SSP1_RegisterByte(); //厂家编号
temp2 =SSP1_RegisterByte();//存储类型
temp3 =SSP1_RegisterByte();//容量

temp =(temp1<<16)|(temp2<<8)|(temp3);

LPC_GPIO0->SET|=(1<<6);//CS=1;

return temp;

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

为增进大家对投入式液位计的认识,本文将对投入式液位计、投入式液位计故障检测、解决方法予以介绍。

关键字: 液位计 指数 投入式液位计

为增进大家对液位计的认识,本文将对磁翻板液位计显示偏低的原因、磁翻板液位计显示虚假的原因予以介绍。

关键字: 液位计 指数 磁翻板液位计

为增进大家对液位计的认识,本文将对各种液位计的安装要求进行介绍。

关键字: 液位计 指数 电容式液位计

为增进大家对安全栅的认识,本文将对隔离式安全栅应用特点、隔离式安全栅工作原理予以介绍。

关键字: 安全栅 指数 隔离式安全栅

为增进大家对安全栅的认识,本文将对隔离器和安全栅的区别以及安全栅的安装守则予以介绍。

关键字: 安全栅 指数 隔离器

为增进大家对安全栅的认识,本文将对安全栅选用方法进行详细的介绍。

关键字: 安全栅 指数 限能电路

为增进大家对自动驾驶的认识,本文将对自动驾驶各级的区别、自动驾驶不能使用燃油车的原因予以介绍。

关键字: 自动驾驶 指数 自动化

为增进大家对自动驾驶的认识,本文将对低速自动驾驶、高速自动驾驶予以介绍。

关键字: 自动驾驶 指数 低速自动驾驶

为增进大家对自动驾驶的认识,本文将对自动驾驶常见的一些问题进行解答。

关键字: 自动驾驶 指数 ADAS

为增进大家对晶振的认识,本文将对晶振不起振的原因以及晶振的一些其它问题予以介绍。

关键字: 晶振 指数 振荡电路
关闭
关闭