打印
[新手园地]

HOT大叔NUC120助学板第十一贴----SPI(PDMA方式)

[复制链接]
12977|16
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 Swallow_0322 于 2011-5-12 17:00 编辑

      板子刚发出去打样,趁机偷个懒,明天再开始编程序,玩玩SPI(PDMA方式)完成对W25Q16BV的读写操作,程序参照新唐例程,望各位高手不吝指教!

源程序见2楼:


工程结构:


串口调试助手调试截图:(仅上电接收内容,具体功能调试同SPI(查询方式))



工程文件:
NUC120_HOT_SPI_PDMA.rar (2.38 MB)

相关帖子

沙发
Swallow_0322|  楼主 | 2011-5-12 16:59 | 只看该作者
源程序如下:
/**************************************************
** 文件名称:NUC120_HOT_SPI.c
** 文件说明:NUC120助学板练习程序
** 创建日期:2011-05-12
** 修改日期:
** 备 注:SPI读写W25Q16BV(PDMA方式)
**************************************************/
#include <stdio.h>
#include "NUC1xx.h"
#include "Driver\DrvGPIO.h"
#include "Driver\DrvSYS.h"
#include "Driver\DrvUART.h"
#include "Driver\DrvSPI.h"
#include "Driver\DrvPDMA.h"

#define Run_Led 2 //2----LED1 3----LED2 4----LED3 5----LED4
#define SPI_CS_PORT E_GPA
#define SPI_CS_PORT_NUM 14
#define Enable_SPI_CS DrvGPIO_ClrBit(SPI_CS_PORT,SPI_CS_PORT_NUM)
#define DISABLE_SPI_CS DrvGPIO_SetBit(SPI_CS_PORT,SPI_CS_PORT_NUM)

volatile uint8_t IsStart = FALSE;
volatile uint8_t Receive_Data = 0;
volatile uint32_t PDMA0_INT_Flag, PDMA1_INT_Flag;
uint8_t SrcArray[256];
uint8_t DestArray[256];


/***************
** 函数声明 **
***************/
void Init_System (void);
void Init_Uart (void);
void UART_INT_HANDLE(uint32_t u32IntStatus);

uint32_t SPI_ReadMidDid(void);
uint32_t SPI_ReadStatusReg1(void);
void SPI_WaitReady(void);
void SPI_ChipErase(void);
void SPI_ReadData(uint32_t StartAddress);
void SPI_PageProgram(uint32_t StartAddress);
void SPI_SectorErase(uint32_t StartAddress);

/*---------------------------------------------------------------------------------------------------------*/
/* PDMA Callback function */
/*---------------------------------------------------------------------------------------------------------*/
void PDMA0_Callback()
{
PDMA0_INT_Flag = 1;
}

void PDMA1_Callback()
{
PDMA1_INT_Flag = 1;
}



/*****************************
** Name: UART_INT_HANDLE
** Function: UART Callback function
** Input: u32IntStatus
** OutPut: None
** Data: 2011-03-17
** Note:
****************************/
void UART_INT_HANDLE(uint32_t u32IntStatus)
{

uint8_t bInChar[1]={0xFF};

if(u32IntStatus & DRVUART_RDAINT)
{
/* Get all the input characters */
while(UART0->ISR.RDA_IF==1)
{
/* Get the character from UART Buffer */
DrvUART_Read(UART_PORT0,bInChar,1);
if (IsStart!=TRUE)
{
IsStart = TRUE;
Receive_Data = bInChar[0];
}
}
}
}

/*****************************
** Name: Init_System
** Function: 系统初始化函数
** Input: None
** OutPut: None
** Data: 2011-03-17
** Note:
****************************/
void Init_System(void)
{
/* Unlock the locked registers before access */
UNLOCKREG(x);

/* Enable the 12MHz oscillator oscillation */
DrvSYS_SetOscCtrl(E_SYS_XTL12M, 1);

/* Waiting for 12M Xtal stable */
DrvSYS_Delay(5000);

LOCKREG(x);
}

/*****************************
** Name: Init_Uart
** Function: UART初始化函数
** Input: None
** OutPut: None
** Data: 2011-03-17
** Note:
****************************/
void Init_Uart(void)
{
STR_UART_T param;

DrvSYS_SelectIPClockSource(E_SYS_UART_CLKSRC,0); //使能UART时钟 UART时钟源选择. 00 =外部12MHz 晶振 01 = PLL 1x =内部 22MHz 振荡器

DrvGPIO_InitFunction(E_FUNC_UART0); //GPB_MFP0-1-2-3置位 GPIO使能UART功能

param.u32BaudRate = 115200; // 波特率
param.u8cDataBits = DRVUART_DATABITS_8; // 数据位
param.u8cStopBits = DRVUART_STOPBITS_1; // 停止位
param.u8cParity = DRVUART_PARITY_NONE; // 校验位
param.u8cRxTriggerLevel = DRVUART_FIFO_1BYTES; // FIFO存储深度 1 字节
param.u8TimeOut = 0; // FIFO超时设定
/* Set UART Configuration */
if(DrvUART_Open(UART_PORT0,¶m) != E_SUCCESS) // 串口开启、结构体整体赋值
printf("UART0 open failed\n");

DrvUART_EnableInt(UART_PORT0, DRVUART_RDAINT,UART_INT_HANDLE);
}

/*****************************
** Name: Init_SPI
** Function: SPI初始化函数
** Input: None
** OutPut: None
** Data: 2011-05-12
** Note:
****************************/
void Init_SPI(void)
{
DrvGPIO_InitFunction(E_FUNC_SPI1);
//GPIO端口初始化为功能SPI1

DrvSPI_Open(eDRVSPI_PORT1, eDRVSPI_MASTER, eDRVSPI_TYPE1, 32,FALSE);
//配置SPI1为主模式 TYPE1波形 32位传输

DrvSPI_SetEndian(eDRVSPI_PORT1, eDRVSPI_MSB_FIRST);
//配置传输比特的顺序:优先发送/接收MSB

DrvSPI_DisableAutoSS(eDRVSPI_PORT1);
//禁止自动片选功能

DrvSPI_SetSlaveSelectActiveLevel(eDRVSPI_PORT1, eDRVSPI_ACTIVE_LOW_FALLING);
//设定从选择线的激活级别:低电平或者下降沿

DrvSPI_SetClockFreq(eDRVSPI_PORT1, 1000000, 0);
//设置SPI的时钟频率为1MHz

DrvGPIO_Open(SPI_CS_PORT,SPI_CS_PORT_NUM, E_IO_OUTPUT); //SPI_FLAH_CS
DISABLE_SPI_CS;

}

/*****************************
** Name: Init_PDMA
** Function: PDMA初始化函数
** Input: None
** OutPut: None
** Data: 2011-05-12
** Note:
****************************/
void Init_PDMA (void)
{
STR_PDMA_T sPDMA;
uint32_t SPIPort;

/* -------------------------------------------- */
/* Configure PDMA Channel 0 to receive SPI2 Rx0 */
/* -------------------------------------------- */
DrvPDMA_Init();
//初始化PDMA(PDMA 控制器时钟使能控制)

/* SPI Port = SPI1 Rx0 */
SPIPort = SPI1_BASE + 0x10;

DrvPDMA_SetCHForAPBDevice(eDRVPDMA_CHANNEL_0, eDRVPDMA_SPI1, eDRVPDMA_READ_APB);
//APB设备选择 PDMA 通道 SPI选择PDMA通道0 读操作

/* CH0 RX Setting */
sPDMA.sSrcCtrl.u32Addr = SPIPort; //源地址
sPDMA.sDestCtrl.u32Addr = (uint32_t)DestArray; //目标地址
sPDMA.u8TransWidth = eDRVPDMA_WIDTH_8BITS; //传输宽度
sPDMA.u8Mode = eDRVPDMA_MODE_APB2MEM; //操作模式: IP到存储器模式 (APB-to-Memory)
sPDMA.sSrcCtrl.eAddrDirection = eDRVPDMA_DIRECTION_FIXED; //传输地址固定
sPDMA.sDestCtrl.eAddrDirection = eDRVPDMA_DIRECTION_INCREMENTED;// 传输地址 持续增加
sPDMA.i32ByteCnt = 256; //字节数
DrvPDMA_Open(eDRVPDMA_CHANNEL_0, &sPDMA);
//配置PDMA通道0

DrvPDMA_EnableInt(eDRVPDMA_CHANNEL_0, eDRVPDMA_BLKD);
//使能PDMA通道0中断 中断源为:eDRVPDMA_BLKD(PDMA Transfer Done 中断使能)

DrvPDMA_InstallCallBack(eDRVPDMA_CHANNEL_0, eDRVPDMA_BLKD, (PFN_DRVPDMA_CALLBACK) PDMA0_Callback );
//PDMA 通道0 安装中断回调函数

/* -------------------------------------------- */
/* Configure PDMA Channel 1 to receive SPI2 Tx0 */
/* -------------------------------------------- */
/* SPI Port = SPI1 Tx0 */
SPIPort = SPI1_BASE + 0x20;
/* PDMA Setting */
DrvPDMA_SetCHForAPBDevice(eDRVPDMA_CHANNEL_1, eDRVPDMA_SPI1, eDRVPDMA_WRITE_APB);
//APB设备选择PDMA通道 SPI选择PDMA通道1 写操作

/* CH0 TX Setting */
sPDMA.sSrcCtrl.u32Addr = (uint32_t)SrcArray; //源地址
sPDMA.sDestCtrl.u32Addr = SPIPort; //目标地址
sPDMA.u8TransWidth = eDRVPDMA_WIDTH_8BITS; //传输宽度
sPDMA.u8Mode = eDRVPDMA_MODE_MEM2APB; //操作模式: 存储器到 IP 模式 (Memory-to-APB)
sPDMA.sSrcCtrl.eAddrDirection = eDRVPDMA_DIRECTION_INCREMENTED; // 传输地址 持续增加
sPDMA.sDestCtrl.eAddrDirection = eDRVPDMA_DIRECTION_FIXED; //传输地址固定
sPDMA.i32ByteCnt = 256;
DrvPDMA_Open(eDRVPDMA_CHANNEL_1, &sPDMA);
////配置PDMA通道1

DrvPDMA_EnableInt(eDRVPDMA_CHANNEL_1, eDRVPDMA_BLKD);
//使能PDMA通道1中断 中断源为:eDRVPDMA_BLKD(PDMA Transfer Done 中断使能)

DrvPDMA_InstallCallBack(eDRVPDMA_CHANNEL_1, eDRVPDMA_BLKD, (PFN_DRVPDMA_CALLBACK) PDMA1_Callback );
//PDMA 通道1 安装中断回调函数
}
int main (void)
{
uint8_t test = 250;
uint32_t Tmp = 0;

Init_System();

Init_Uart();

Init_SPI();

Init_PDMA();

DrvGPIO_Open(E_GPA,Run_Led, E_IO_OUTPUT); //程序运行指示
DrvGPIO_ClrBit(E_GPA,Run_Led);


printf("\n");
printf("/*==========================\n");
printf("======菜农 %d 助学计划======\n",test);
printf("========NUC120助学板========\n");
printf("======程序参考新唐例程======\n");
printf("=======2011年05月12日=======\n");
printf("======SPI实验(PDMA方式)=====\n");
SPI_WaitReady();
Tmp = SPI_ReadMidDid();
printf("W25Q16BV制造商ID及设备ID为:0x%X\n",Tmp);

//W25Q16BV Page 0 初始化
SPI_WaitReady();
DrvPDMA_CHEnableTransfer(eDRVPDMA_CHANNEL_0); //使能PDMA通道0
SPI_ReadData(0x1000);
if (DestArray[0]!=0xAA)
{
SrcArray[0] = 0xAA;
SPI_WaitReady();
SPI_ChipErase();
SPI_WaitReady();
DrvPDMA_CHEnableTransfer(eDRVPDMA_CHANNEL_1); //使能PDMA通道1
SPI_PageProgram(0x1000);

for (Tmp=0;Tmp<256;Tmp++)
SrcArray[Tmp] = Tmp;
SPI_WaitReady();
DrvPDMA_CHEnableTransfer(eDRVPDMA_CHANNEL_1); //使能PDMA通道1
SPI_PageProgram(0);
}

//W25Q16BV Page 0 读取
printf("Read Flash (Page 0) ...\n");
SPI_WaitReady();
DrvPDMA_CHEnableTransfer(eDRVPDMA_CHANNEL_0); //使能PDMA通道0
SPI_ReadData(0);
for (Tmp=0;Tmp<256;Tmp++)
{
printf("0x%X ",DestArray[Tmp]);
if ((Tmp%16)==15)printf("\n");
}
printf("Read Flash (Page 0) done!\n");

printf("'R/r'为读指令、'U/u'为Page 0加1并存储指令、'D/d'为Page 0减1并存储指令\n");
printf("====请输入字符开始测试!===\n");
printf("==========================*/\n");

while(1)
{
if (IsStart)
{
switch (Receive_Data)
{
case 'R':
case 'r':
printf("Read Flash (Page 0) ...\n");
SPI_WaitReady();
DrvPDMA_CHEnableTransfer(eDRVPDMA_CHANNEL_0); //使能PDMA通道0
SPI_ReadData(0);
for (Tmp=0;Tmp<256;Tmp++)
{
printf("0x%X ",DestArray[Tmp]);
if ((Tmp%16)==15)printf("\n");
}
printf("Read Flash (Page 0) done!\n");
break;
case 'U':
case 'u':
printf("rogram Flash (Page 0)[Add 1] ...\n");
SPI_WaitReady();
DrvPDMA_CHEnableTransfer(eDRVPDMA_CHANNEL_0); //使能PDMA通道0
SPI_ReadData(0);
for (Tmp=0;Tmp<256;Tmp++)
{
SrcArray[Tmp] = DestArray[Tmp]+1;
}
SPI_WaitReady();
SPI_SectorErase(0x0000);
SPI_WaitReady();
DrvPDMA_CHEnableTransfer(eDRVPDMA_CHANNEL_1); //使能PDMA通道1
SPI_PageProgram(0);
printf("rogram Flash (Page 0)[Add 1] done!\n");
break;
case 'D':
case 'd':
printf("rogram Flash (Page 0)[Minus 1] ...\n");
SPI_WaitReady();
DrvPDMA_CHEnableTransfer(eDRVPDMA_CHANNEL_0); //使能PDMA通道0
SPI_ReadData(0);
for (Tmp=0;Tmp<256;Tmp++)
{
SrcArray[Tmp] = DestArray[Tmp]-1;
}
SPI_WaitReady();
SPI_SectorErase(0x0000);
SPI_WaitReady();
DrvPDMA_CHEnableTransfer(eDRVPDMA_CHANNEL_1); //使能PDMA通道1
SPI_PageProgram(0);
printf("rogram Flash (Page 0)[Minus 1] done!\n");
break;
default:
printf("请确认您输入的指令是否合法!\n");

}
IsStart = FALSE;
}
}
}

/*****************************
** Name: SPI_ReadMidDid
** Function: W25Q16BV读制造商ID及设备ID函数
** Input: None
** OutPut: MID & DID
** Data: 2011-05-07
** Note:
****************************/
uint32_t SPI_ReadMidDid(void)
{
uint32_t au32SourceData;
uint32_t au32DestinationData;

DrvSPI_SetBitLength(eDRVSPI_PORT1, 8);
//配置SPI传输的比特长度:8 bits

Enable_SPI_CS;
//激活/配置从设备片选信号

au32SourceData = 0x90;
DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData);
//发送数据到 SPI 总线: 0x90 (Read Manufacturer/Device ID)

while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {}
//等待SPI端口空闲

DrvSPI_SetBitLength(eDRVSPI_PORT1, 24);
//配置SPI传输的比特长度:24 bits

au32SourceData = 0x0;
DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData);
//发送数据到 SPI 总线: 0x00 (24-bit Address)

while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {}
//等待SPI端口空闲

DrvSPI_SetBitLength(eDRVSPI_PORT1, 16);
//配置SPI传输的比特长度:16 bits


au32SourceData = 0x0;
DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData);
//接收数据

while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {}
//等待SPI端口空闲

DISABLE_SPI_CS;
//从设备片选信号取消激活

DrvSPI_DumpRxRegister(eDRVSPI_PORT1, &au32DestinationData, 1);
//从接收寄存器读数据. 但是不触发下一次数据传输.

return (au32DestinationData & 0xffff);
}

/*****************************
** Name: SPI_ReadStatusReg1
** Function: W25Q16BV读状态寄存器1函数
** Input: None
** OutPut: ReadStatusReg1
** Data: 2011-05-07
** Note:
****************************/
uint32_t SPI_ReadStatusReg1(void)
{
uint32_t au32SourceData;
uint32_t au32DestinationData;

DrvSPI_SetBitLength(eDRVSPI_PORT1, 16);
//配置SPI传输的比特长度:16 bits

Enable_SPI_CS;
//激活/配置从设备片选信号

au32SourceData = 0x0500;
DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData);
//发送数据到 SPI 总线: 0x0500 (Read status register 1)

while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {}
//等待SPI端口空闲

DISABLE_SPI_CS;
//从设备片选信号取消激活

DrvSPI_DumpRxRegister(eDRVSPI_PORT1, &au32DestinationData, 1);
//从接收寄存器读数据. 但是不触发下一次数据传输.

return (au32DestinationData & 0xFF);
}

/*****************************
** Name: SPI_WaitReady
** Function: W25Q16BV忙状态检查函数
** Input: None
** OutPut: None
** Data: 2011-05-07
** Note:
****************************/
void SPI_WaitReady(void)
{
uint32_t ReturnValue;

do{
ReturnValue = SPI_ReadStatusReg1();
ReturnValue = ReturnValue & 1;
}while(ReturnValue!=0);
//检查从设备状态寄存器1的BUSY位 等待其为0
}

/*****************************
** Name: SPI_ChipErase
** Function: W25Q16BV片擦除函数
** Input: None
** OutPut: None
** Data: 2011-05-07
** Note:
****************************/
void SPI_ChipErase(void)
{

uint32_t au32SourceData;

DrvSPI_SetBitLength(eDRVSPI_PORT1, 8);
//配置SPI传输的比特长度:8 bits

Enable_SPI_CS;
//激活/配置从设备片选信号

au32SourceData = 0x06;
DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData);
//发送数据到 SPI 总线: 0x06 (Write enable)

while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {}
//等待SPI端口空闲

DISABLE_SPI_CS;
//从设备片选信号取消激活

Enable_SPI_CS;
//激活/配置从设备片选信号

au32SourceData = 0xC7;
DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData);
//发送数据到 SPI 总线: 0xC7 (Chip Erase)

while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {}
//等待SPI端口空闲

DISABLE_SPI_CS;
//从设备片选信号取消激活
}

/*****************************
** Name: SPI_ReadData
** Function: W25Q16BV读数据函数
** Input: StartAddress
** OutPut: None
** Data: 2011-05-12
** Note:
****************************/
void SPI_ReadData(uint32_t StartAddress)
{
uint32_t au32SourceData;

DrvSPI_SetBitLength(eDRVSPI_PORT1, 8);
//配置SPI传输的比特长度:8 bits

Enable_SPI_CS;
//激活/配置从设备片选信号

au32SourceData = 0x03;
DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData);
//发送数据到 SPI 总线: 0x03 (Read data)

while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {}
//等待SPI端口空闲

DrvSPI_SetBitLength(eDRVSPI_PORT1, 24);
//配置SPI传输的比特长度:24 bits

au32SourceData = StartAddress;
DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData);
//发送数据到 SPI 总线: StartAddress

while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {}
//等待SPI端口空闲

DrvSPI_SetBitLength(eDRVSPI_PORT1, 8);
//配置SPI传输的比特长度:8 bits

DrvSPI_SetPDMA(eDRVSPI_PORT1, eDRVSPI_RX_DMA, TRUE);
//使能SPI1,PDMA且模式为DMA-Receiving模式

PDMA0_INT_Flag = 0;
DrvSPI_SetGo(eDRVSPI_PORT1);
//设定GO_BUSY 比特来触发 SPI 数据传输.

while (1)
{
// 等待 PDMA0 接收结束
if (PDMA0_INT_Flag)
{
PDMA0_INT_Flag = 0;
break;
}
}

DISABLE_SPI_CS;
//从设备片选信号取消激活
}

/*****************************
** Name: SPI_PageProgram
** Function: W25Q16BV按页编程函数
** Input: StartAddress
** OutPut: None
** Data: 2011-05-12
** Note:
****************************/
void SPI_PageProgram(uint32_t StartAddress)
{
uint32_t au32SourceData;

DrvSPI_SetBitLength(eDRVSPI_PORT1, 8);
//配置SPI传输的比特长度:8 bits

Enable_SPI_CS;
//激活/配置从设备片选信号

au32SourceData = 0x06;
DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData);
//发送数据到 SPI 总线: 0x06 (Write enable)

while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {}
//等待SPI端口空闲

DISABLE_SPI_CS;
//从设备片选信号取消激活

Enable_SPI_CS;
//激活/配置从设备片选信号

au32SourceData = 0x02;
DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData);
//发送数据到 SPI 总线: 0x02 (Page program)

while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {}
//等待SPI端口空闲

DrvSPI_SetBitLength(eDRVSPI_PORT1, 24);
//配置SPI传输的比特长度:24 bits

au32SourceData = StartAddress;
DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData);
//发送数据到 SPI 总线: StartAddress

while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {}
//等待SPI端口空闲

DrvSPI_SetBitLength(eDRVSPI_PORT1, 8);
//配置SPI传输的比特长度:8 bits

DrvSPI_SetPDMA(eDRVSPI_PORT1, eDRVSPI_TX_DMA, TRUE);
//使能SPI1且模式为DMA-Transmitting模式

PDMA1_INT_Flag = 0;
DrvSPI_SetGo(eDRVSPI_PORT1);
//设定GO_BUSY 比特来触发 SPI 数据传输.

while (1)
{
// 等待 PDMA1 传输结束
if (PDMA1_INT_Flag)
{
PDMA1_INT_Flag = 0;
break;
}
}

DISABLE_SPI_CS;
//从设备片选信号取消激活
}

/*****************************
** Name: SPI_SectorErase
** Function: W25Q16BV扇区擦除函数
** Input: StartAddress
** OutPut: None
** Data: 2011-05-07
** Note:
****************************/
void SPI_SectorErase(uint32_t StartAddress)
{

uint32_t au32SourceData;

DrvSPI_SetBitLength(eDRVSPI_PORT1, 8);
//配置SPI传输的比特长度:8 bits

Enable_SPI_CS;
//激活/配置从设备片选信号

au32SourceData = 0x06;
DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData);
//发送数据到 SPI 总线: 0x06 (Write enable)

while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {}
//等待SPI端口空闲

DISABLE_SPI_CS;
//从设备片选信号取消激活

DrvSPI_SetBitLength(eDRVSPI_PORT1, 8);
//配置SPI传输的比特长度:8 bits

Enable_SPI_CS;
//激活/配置从设备片选信号

au32SourceData = 0x20;
DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData);
//发送数据到 SPI 总线: 0x20 (Sector Erase)

while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {}
//等待SPI端口空闲

DrvSPI_SetBitLength(eDRVSPI_PORT1, 24);
//配置SPI传输的比特长度:24 bits

au32SourceData = StartAddress&0xFFF000;
DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData);
//发送数据到 SPI 总线: StartAddress

while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {}
//等待SPI端口空闲

DISABLE_SPI_CS;
//从设备片选信号取消激活
}

使用特权

评论回复
板凳
hotpower| | 2011-5-13 00:34 | 只看该作者
好样的,再谈谈两种方式的差别~~~

使用特权

评论回复
地板
Swallow_0322|  楼主 | 2011-5-13 07:59 | 只看该作者
呵呵!
拿洗衣机打个比方:
    查询方式就相当于老式的洗衣机,加水加洗衣粉放入衣物洗涤,开启电源在那等待到洗涤结束,然后取衣物放入甩干桶,再等待,甩干结束拿出去晾晒;
    PDMA方式就相当于全自动洗衣机,加衣物及洗衣粉,打开电源不管了,去做饭,去玩,爱干啥干啥,听到结束报警声去取出衣物晾干完事,而且洗涤效果优于老式洗衣机。
   比喻也许不恰当,望大叔不要见笑!

使用特权

评论回复
5
hotpower| | 2011-5-13 08:58 | 只看该作者
比喻的有些怪异,好玩。
pdma是一种数据直接交换。不用cpu干预。
例如本例是内存数据与spi接口的数据交换。它只需你设置好后启动pdma即可,不用你每个字都去存取,特别适于批量操作。
你只需要设置内存地址和spi接口即可。
节省了查询或中断的时间。

使用特权

评论回复
6
Swallow_0322|  楼主 | 2011-5-13 17:29 | 只看该作者
呵呵!
突发奇想的比喻,表述不是很清楚!(*^__^*) 嘻嘻

我的意思是老式洗衣机每个步骤都需要人工干预而且得等待,而全自动洗衣机放入衣物打开电源就可以干其它事情,无需人工干预,洗衣结束后后告警即PDMA中断提醒操作者操作结束。

使用特权

评论回复
7
ichuangj| | 2011-5-17 15:06 | 只看该作者
好!马克

使用特权

评论回复
8
fomula| | 2011-5-20 00:06 | 只看该作者
没调过SPI,想请教nrf24l01这种无线收发模块能用这种PDMA方式吗,直接交换数据,不用CPU干预?

使用特权

评论回复
9
Swallow_0322|  楼主 | 2011-5-20 07:43 | 只看该作者
我认为这个和你使用的具体芯片无关,只要你使用SPI、ADC、UART或者USB都可以通过PDMA方式进行数据交换!
以上仅为菜鸟的一般理解,如果有误请谅解!

使用特权

评论回复
10
fomula| | 2011-5-21 15:41 | 只看该作者
谢谢楼上的,我调的试试,调通了nrf24l01的PDMA,放上来共享。

使用特权

评论回复
11
lixupengarm| | 2011-5-22 18:49 | 只看该作者
mark!!

使用特权

评论回复
12
weshiluwei6| | 2011-5-26 13:04 | 只看该作者
支持大哥的 MARK 回头学习

使用特权

评论回复
13
564451696| | 2011-10-25 09:46 | 只看该作者
这个还要顶。。。

使用特权

评论回复
14
huzaizai007| | 2012-4-5 16:05 | 只看该作者
学习中

使用特权

评论回复
15
yongjun_meng| | 2012-5-2 08:42 | 只看该作者
谢谢分享

使用特权

评论回复
16
JIESHENGKEJI| | 2013-5-7 12:35 | 只看该作者
学习中,谢谢分享

使用特权

评论回复
17
sunbingbing| | 2013-5-10 07:30 | 只看该作者
[em:2:

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:播种一种行为,收获一种习惯;播种一种习惯,收获一种性格;播种一种性格,收获一种人生!

121

主题

1393

帖子

4

粉丝