本帖最后由 sh007 于 2011-11-17 13:07 编辑
拿到板子 本来想尽快学习使用,但是工作实在忙得没能按计划进行。最近也用到SPI FLASH,所以就先忽悠这个吧。
板子上的串口 看来挺多人跟我一样 打印不了的。我用的是USBTOCOM的线,看资料调了一下串口,居然没反应,再我插拔串口线时,数据出来了,很奇怪,看了原理图后发现,串口的三个控制端也都引出,而且DTR还接了复位信号控制。但拔出来后DTR脚接触不好时,通讯就正常了。所以就先把R5,R6先焊掉,以后再研究串口控制。先不说上代码先。
SPI_PDMA_W25Q16BV.C主控函数文件
设置主频50MHz,SPI 12MHz,然后对SPI FLASH 擦除,写和读进行操作/*---------------------------------------------------------------------------------------------------------*/
/* */
/* Copyright(c) 2011 Nuvoton Technology Corp. All rights reserved. */
/*---------------------------------------------------------------------------------------------------------*/
#include <stdio.h>
#include "NUC1xx.h"
#include "DrvUART.h"
#include "DrvSYS.h"
#include "DrvSPI.h"
#include "DrvPDMA.h"
#include "SPI_FLASH_PDMA.h"
#include "Driver\DrvGPIO.h"
#define RW_LEN 80
uint8_t SPI_PDMA_RXBuf[RW_LEN];
uint8_t SPI_PDMA_TXBuf[RW_LEN];
void RCC_Config(void);
void UART_Config(void);
int main()
{
uint16_t writenum,readnum;
RCC_Config();
UART_Config();
SPI_Init();
PDMA_Init(RW_LEN);
printf("\n");
printf("+----------------------------------------------------------------------+\n");
printf("| NUC120助学板之SPI PDMA FLASH---W25Q16BV |\n");
printf("+----------------------------------------------------------------------+\n");
printf("***NUC120***配置主频为: %2d MHz.\n",DrvSYS_GetHCLKFreq()/1000000);
printf("---SPI1主机模式,频率为: %2d MHz.\n", DrvSPI_GetClock1Freq(eDRVSPI_PORT1)/1000000);
printf("开始擦除整片FLASH...\n");
SPIFlash_ChipErase();
SPIFlash_WaitReady();
printf("整片FLASH擦除完成。\n");
for(writenum=0;writenum<RW_LEN;writenum++)
{
SPI_PDMA_TXBuf[writenum]= writenum;
SPI_PDMA_RXBuf[writenum]= 0;
}
DrvSYS_Delay(500000);
printf("开始写入数据:\n");
// Trigger PDMA specified Channel
DrvPDMA_CHEnableTransfer(eDRVPDMA_CHANNEL_1);
SPIFlash_PDMA_PageProgram(0x0);
for(writenum=0;writenum<RW_LEN;writenum++)
{
if(writenum%16 == 0 ) printf("\n");
printf("0x%x,", SPI_PDMA_TXBuf[writenum]);
}
DrvSYS_Delay(500000);
printf("开始读出数据:\n");
// Trigger PDMA specified Channel
DrvPDMA_CHEnableTransfer(eDRVPDMA_CHANNEL_0);
SPIFlash_PDMA_Read(0x0);
for(readnum=0;readnum<RW_LEN;readnum++)
{
if(readnum%16 == 0 ) printf("\n");
printf("0x%x,", SPI_PDMA_RXBuf[readnum]);
}
while(1)
{}
}
void RCC_Config(void)
{
UNLOCKREG();
SYSCLK->WRCON.XTL12M_EN = 1;
// Waiting for 12M Xtal stalble
DrvSYS_Delay(5000);
//HCLK 为外部12M 通过PLL倍频到 50MHz.
DrvSYS_Open(50000000);
DrvSYS_Delay(5000);
LOCKREG();
}
void UART_Config()
{
STR_UART_T sParam;
// Set UART I/O
DrvGPIO_InitFunction(E_FUNC_UART0);
//Select UART Clock Source From 12MHz
DrvSYS_SelectIPClockSource(E_SYS_UART_CLKSRC, 0);
// UART Setting
sParam.u32BaudRate = 9600;
sParam.u8cDataBits = DRVUART_DATABITS_8;
sParam.u8cStopBits = DRVUART_STOPBITS_1;
sParam.u8cParity = DRVUART_PARITY_NONE;
sParam.u8cRxTriggerLevel= DRVUART_FIFO_1BYTES;
// Set UART Configuration
DrvUART_Open(UART_PORT0, &sParam);
}
SPI_FLASH_PDMA.c SPI 利用PDMA进行读写的操作函数。
#include <stdio.h>
#include "NUC1xx.h"
#include "DrvUART.h"
#include "DrvSYS.h"
#include "DrvSPI.h"
#include "DrvGPIO.h"
#include "DrvPDMA.h"
#include "SPI_FLASH_PDMA.h"
#define Enable_SPI1_W25Q16BV (GPIOA->DOUT &= ~(1 << 14))
#define Disable_SPI1_W25Q16BV (GPIOA->DOUT |= (1 << 14))
void PDMA0_Callback(void);
void PDMA1_Callback(void);
volatile uint32_t PDMA0_INT_Flag, PDMA1_INT_Flag;
STR_PDMA_T sPDMA;
uint32_t SPIPort;
uint32_t u32ByteCount, u32FlashAddress, u32PageNumber;
extern uint8_t SPI_PDMA_RXBuf[];
extern uint8_t SPI_PDMA_TXBuf[];
void SPI_Init(void)
{
//SPI1 GPIO Init
DrvGPIO_InitFunction(E_FUNC_SPI1);
//Initialize SPI
// Configure SPI0 as a master, 32-bit transaction
DrvSPI_Open(eDRVSPI_PORT1, eDRVSPI_MASTER, eDRVSPI_TYPE1, 32,FALSE);
// MSB first
DrvSPI_SetEndian(eDRVSPI_PORT1, eDRVSPI_MSB_FIRST);
// Set the active level of slave select.
DrvSPI_SetSlaveSelectActiveLevel(eDRVSPI_PORT1, eDRVSPI_ACTIVE_LOW_FALLING);
// SPI clock rate 12MHz
DrvSPI_SetClockFreq(eDRVSPI_PORT1,12000000, 0);
//设置PA14为输出,PA14为W25Q16BV的位选
DrvGPIO_Open(E_GPA, 14, E_IO_OUTPUT);
}
void PDMA_Init(uint16_t RW_LEN)
{
/* -------------------------------------------- */
/* Configure PDMA Channel 0 to receive SPI1 Rx0 */
/* -------------------------------------------- */
// PDMA Init
DrvPDMA_Init();
// SPI Port = SPI1 Rx0
SPIPort = SPI1_BASE + 0x10;
// PDMA Setting
DrvPDMA_SetCHForAPBDevice(eDRVPDMA_CHANNEL_0, eDRVPDMA_SPI1, eDRVPDMA_READ_APB);
// CH0 RX Setting
sPDMA.sSrcCtrl.u32Addr = SPIPort; //源地址
sPDMA.sDestCtrl.u32Addr = (uint32_t)SPI_PDMA_RXBuf;//目标地址,这里是内部RAM的一块区域
sPDMA.u8TransWidth = eDRVPDMA_WIDTH_8BITS;
sPDMA.u8Mode = eDRVPDMA_MODE_APB2MEM;
sPDMA.sSrcCtrl.eAddrDirection = eDRVPDMA_DIRECTION_FIXED;
sPDMA.sDestCtrl.eAddrDirection = eDRVPDMA_DIRECTION_INCREMENTED;
sPDMA.i32ByteCnt = RW_LEN;
DrvPDMA_Open(eDRVPDMA_CHANNEL_0, &sPDMA);
// Enable INT
DrvPDMA_EnableInt(eDRVPDMA_CHANNEL_0, eDRVPDMA_BLKD);
// Install Callback function
DrvPDMA_InstallCallBack(eDRVPDMA_CHANNEL_0, eDRVPDMA_BLKD, (PFN_DRVPDMA_CALLBACK) PDMA0_Callback );
/* -------------------------------------------- */
/* Configure PDMA Channel 1 to receive SPI1 Tx0 */
/* -------------------------------------------- */
// SPI Port = SPI1 Tx0
SPIPort = SPI1_BASE + 0x20;
// PDMA Setting
DrvPDMA_SetCHForAPBDevice(eDRVPDMA_CHANNEL_1, eDRVPDMA_SPI1, eDRVPDMA_WRITE_APB);
// CH0 TX Setting
sPDMA.sSrcCtrl.u32Addr = (uint32_t)SPI_PDMA_TXBuf;
sPDMA.sDestCtrl.u32Addr = SPIPort;
sPDMA.u8TransWidth = eDRVPDMA_WIDTH_8BITS;
sPDMA.u8Mode = eDRVPDMA_MODE_MEM2APB;
sPDMA.sSrcCtrl.eAddrDirection = eDRVPDMA_DIRECTION_INCREMENTED;
sPDMA.sDestCtrl.eAddrDirection = eDRVPDMA_DIRECTION_FIXED;
sPDMA.i32ByteCnt = RW_LEN;
DrvPDMA_Open(eDRVPDMA_CHANNEL_1, &sPDMA);
// Enable INT
DrvPDMA_EnableInt(eDRVPDMA_CHANNEL_1, eDRVPDMA_BLKD);
// Install Callback function
DrvPDMA_InstallCallBack(eDRVPDMA_CHANNEL_1, eDRVPDMA_BLKD, (PFN_DRVPDMA_CALLBACK) PDMA1_Callback );
}
void SPIFlash_PDMA_PageProgram(uint32_t StartAddr)
{
uint32_t au32SourceData;
// configure transaction length as 8 bits
DrvSPI_SetBitLength(eDRVSPI_PORT1, 8);
//CS =0 使能W25Q16BV
Enable_SPI1_W25Q16BV;
// send Command: 0x06, Write enable
au32SourceData = 0x06;
DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData);
// wait
while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {}
//CS =1 禁止W25Q16BV
Disable_SPI1_W25Q16BV;
//CS =0 使能W25Q16BV
Enable_SPI1_W25Q16BV;
// send Command: 0x02, Page program
au32SourceData = 0x02;
DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData);
// wait
while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {}
// configure transaction length as 24 bits
DrvSPI_SetBitLength(eDRVSPI_PORT1, 24);
// send 24-bit start address
au32SourceData = StartAddr;
DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData);
// wait
while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {}
// configure transaction length as 8 bits
DrvSPI_SetBitLength(eDRVSPI_PORT1, 8);
// enable SPI PDMA
DrvSPI_SetPDMA(eDRVSPI_PORT1, eDRVSPI_TX_DMA, TRUE);
// SPI go
PDMA1_INT_Flag = 0;
DrvSPI_SetGo(eDRVSPI_PORT1);
// wait PDMA1 done
while (1)
{
if (PDMA1_INT_Flag)
{
PDMA1_INT_Flag = 0;
break;
}
}
//CS =1 禁止W25Q16BV
Disable_SPI1_W25Q16BV;
}
void SPIFlash_PDMA_Read(uint32_t StartAddr)
{
uint32_t au32SourceData;
// configure transaction length as 8 bits
DrvSPI_SetBitLength(eDRVSPI_PORT1, 8);
//CS =0 使能W25Q16BV
Enable_SPI1_W25Q16BV;
// send Command: 0x03, Read data
au32SourceData = 0x03;
DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData);
// wait
while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {}
// configure transaction length as 24 bits
DrvSPI_SetBitLength(eDRVSPI_PORT1, 24);
// send 24-bit start address
au32SourceData = StartAddr;
DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData);
// wait
while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {}
// configure transaction length as 8 bits
DrvSPI_SetBitLength(eDRVSPI_PORT1, 8);
// enable SPI PDMA
DrvSPI_SetPDMA(eDRVSPI_PORT1, eDRVSPI_RX_DMA, TRUE);
// SPI go
PDMA0_INT_Flag = 0;
DrvSPI_SetGo(eDRVSPI_PORT1);
// wait PDMA0 done
while (1)
{
if (PDMA0_INT_Flag)
{
PDMA0_INT_Flag = 0;
break;
}
}
//CS =1 禁止W25Q16BV
Disable_SPI1_W25Q16BV;
}
uint32_t SPIFlash_ReadStatusReg(void)
{
uint32_t au32SourceData;
uint32_t au32DestinationData;
// configure transaction length as 16 bits
DrvSPI_SetBitLength(eDRVSPI_PORT1, 16);
//CS =0 使能W25Q16BV
Enable_SPI1_W25Q16BV;
// send Command: 0x05, Read status register 1
au32SourceData = 0x0500;
DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData);
// wait
while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {}
//CS =1 禁止W25Q16BV
Disable_SPI1_W25Q16BV;
// dump Rx register
DrvSPI_DumpRxRegister(eDRVSPI_PORT1, &au32DestinationData, 1);
return (au32DestinationData & 0xFF);
}
void SPIFlash_WaitReady(void)
{
uint32_t ReturnValue;
do{
ReturnValue = SPIFlash_ReadStatusReg();
ReturnValue = ReturnValue & 1;
}while(ReturnValue!=0); // check the BUSY bit
}
void SPIFlash_ChipErase(void)
{
uint32_t au32SourceData;
// configure transaction length as 8 bits
DrvSPI_SetBitLength(eDRVSPI_PORT1, 8);
//CS =0 使能W25Q16BV
Enable_SPI1_W25Q16BV;
// send Command: 0x06, Write enable
au32SourceData = 0x06;
DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData);
// wait
while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {}
//CS =1 禁止W25Q16BV
Disable_SPI1_W25Q16BV;
//CS =0 使能W25Q16BV
Enable_SPI1_W25Q16BV;
// send Command: 0xC7, Chip Erase
au32SourceData = 0xc7;
DrvSPI_SingleWrite(eDRVSPI_PORT1, &au32SourceData);
// wait
while (DrvSPI_IsBusy(eDRVSPI_PORT1)) {}
//CS =1 禁止W25Q16BV
Disable_SPI1_W25Q16BV;
}
/*---------------------------------------------------------------------------------------------------------*/
/* PDMA Callback function */
/*---------------------------------------------------------------------------------------------------------*/
void PDMA0_Callback(void)
{
PDMA0_INT_Flag = 1;
}
void PDMA1_Callback(void)
{
PDMA1_INT_Flag = 1;
}
|
|