[新手园地] HOT大叔NUC120助学板第十一贴----SPI(PDMA方式)

[复制链接]
 楼主| Swallow_0322 发表于 2011-5-12 16:49 | 显示全部楼层 |阅读模式
本帖最后由 Swallow_0322 于 2011-5-12 17:00 编辑

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

源程序见2楼:


工程结构:


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



工程文件:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
 楼主| Swallow_0322 发表于 2011-5-12 16:59 | 显示全部楼层
源程序如下:
  1. /**************************************************
  2. ** 文件名称:NUC120_HOT_SPI.c
  3. ** 文件说明:NUC120助学板练习程序
  4. ** 创建日期:2011-05-12
  5. ** 修改日期:
  6. ** 备 注:SPI读写W25Q16BV(PDMA方式)
  7. **************************************************/
  8. #include <stdio.h>
  9. #include "NUC1xx.h"
  10. #include "Driver\DrvGPIO.h"
  11. #include "Driver\DrvSYS.h"
  12. #include "Driver\DrvUART.h"
  13. #include "Driver\DrvSPI.h"
  14. #include "Driver\DrvPDMA.h"

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

  20. volatile uint8_t IsStart = FALSE;
  21. volatile uint8_t Receive_Data = 0;
  22. volatile uint32_t PDMA0_INT_Flag, PDMA1_INT_Flag;
  23. uint8_t SrcArray[256];
  24. uint8_t DestArray[256];


  25. /***************
  26. ** 函数声明 **
  27. ***************/
  28. void Init_System (void);
  29. void Init_Uart (void);
  30. void UART_INT_HANDLE(uint32_t u32IntStatus);

  31. uint32_t SPI_ReadMidDid(void);
  32. uint32_t SPI_ReadStatusReg1(void);
  33. void SPI_WaitReady(void);
  34. void SPI_ChipErase(void);
  35. void SPI_ReadData(uint32_t StartAddress);
  36. void SPI_PageProgram(uint32_t StartAddress);
  37. void SPI_SectorErase(uint32_t StartAddress);

  38. /*---------------------------------------------------------------------------------------------------------*/
  39. /* PDMA Callback function */
  40. /*---------------------------------------------------------------------------------------------------------*/
  41. void PDMA0_Callback()
  42. {
  43. PDMA0_INT_Flag = 1;
  44. }

  45. void PDMA1_Callback()
  46. {
  47. PDMA1_INT_Flag = 1;
  48. }



  49. /*****************************
  50. ** Name: UART_INT_HANDLE
  51. ** Function: UART Callback function
  52. ** Input: u32IntStatus
  53. ** OutPut: None
  54. ** Data: 2011-03-17
  55. ** Note:
  56. ****************************/
  57. void UART_INT_HANDLE(uint32_t u32IntStatus)
  58. {

  59. uint8_t bInChar[1]={0xFF};

  60. if(u32IntStatus & DRVUART_RDAINT)
  61. {
  62. /* Get all the input characters */
  63. while(UART0->ISR.RDA_IF==1)
  64. {
  65. /* Get the character from UART Buffer */
  66. DrvUART_Read(UART_PORT0,bInChar,1);
  67. if (IsStart!=TRUE)
  68. {
  69. IsStart = TRUE;
  70. Receive_Data = bInChar[0];
  71. }
  72. }
  73. }
  74. }

  75. /*****************************
  76. ** Name: Init_System
  77. ** Function: 系统初始化函数
  78. ** Input: None
  79. ** OutPut: None
  80. ** Data: 2011-03-17
  81. ** Note:
  82. ****************************/
  83. void Init_System(void)
  84. {
  85. /* Unlock the locked registers before access */
  86. UNLOCKREG(x);

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

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

  91. LOCKREG(x);
  92. }

  93. /*****************************
  94. ** Name: Init_Uart
  95. ** Function: UART初始化函数
  96. ** Input: None
  97. ** OutPut: None
  98. ** Data: 2011-03-17
  99. ** Note:
  100. ****************************/
  101. void Init_Uart(void)
  102. {
  103. STR_UART_T param;

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

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

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

  115. DrvUART_EnableInt(UART_PORT0, DRVUART_RDAINT,UART_INT_HANDLE);
  116. }

  117. /*****************************
  118. ** Name: Init_SPI
  119. ** Function: SPI初始化函数
  120. ** Input: None
  121. ** OutPut: None
  122. ** Data: 2011-05-12
  123. ** Note:
  124. ****************************/
  125. void Init_SPI(void)
  126. {
  127. DrvGPIO_InitFunction(E_FUNC_SPI1);
  128. //GPIO端口初始化为功能SPI1

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

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

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

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

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

  139. DrvGPIO_Open(SPI_CS_PORT,SPI_CS_PORT_NUM, E_IO_OUTPUT); //SPI_FLAH_CS
  140. DISABLE_SPI_CS;

  141. }

  142. /*****************************
  143. ** Name: Init_PDMA
  144. ** Function: PDMA初始化函数
  145. ** Input: None
  146. ** OutPut: None
  147. ** Data: 2011-05-12
  148. ** Note:
  149. ****************************/
  150. void Init_PDMA (void)
  151. {
  152. STR_PDMA_T sPDMA;
  153. uint32_t SPIPort;

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

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

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

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

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

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

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

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

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

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

  204. Init_System();

  205. Init_Uart();

  206. Init_SPI();

  207. Init_PDMA();

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


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

  220. //W25Q16BV Page 0 初始化
  221. SPI_WaitReady();
  222. DrvPDMA_CHEnableTransfer(eDRVPDMA_CHANNEL_0); //使能PDMA通道0
  223. SPI_ReadData(0x1000);
  224. if (DestArray[0]!=0xAA)
  225. {
  226. SrcArray[0] = 0xAA;
  227. SPI_WaitReady();
  228. SPI_ChipErase();
  229. SPI_WaitReady();
  230. DrvPDMA_CHEnableTransfer(eDRVPDMA_CHANNEL_1); //使能PDMA通道1
  231. SPI_PageProgram(0x1000);

  232. for (Tmp=0;Tmp<256;Tmp++)
  233. SrcArray[Tmp] = Tmp;
  234. SPI_WaitReady();
  235. DrvPDMA_CHEnableTransfer(eDRVPDMA_CHANNEL_1); //使能PDMA通道1
  236. SPI_PageProgram(0);
  237. }

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

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

  252. while(1)
  253. {
  254. if (IsStart)
  255. {
  256. switch (Receive_Data)
  257. {
  258. case 'R':
  259. case 'r':
  260. printf("Read Flash (Page 0) ...\n");
  261. SPI_WaitReady();
  262. DrvPDMA_CHEnableTransfer(eDRVPDMA_CHANNEL_0); //使能PDMA通道0
  263. SPI_ReadData(0);
  264. for (Tmp=0;Tmp<256;Tmp++)
  265. {
  266. printf("0x%X ",DestArray[Tmp]);
  267. if ((Tmp%16)==15)printf("\n");
  268. }
  269. printf("Read Flash (Page 0) done!\n");
  270. break;
  271. case 'U':
  272. case 'u':
  273. printf("rogram Flash (Page 0)[Add 1] ...\n");
  274. SPI_WaitReady();
  275. DrvPDMA_CHEnableTransfer(eDRVPDMA_CHANNEL_0); //使能PDMA通道0
  276. SPI_ReadData(0);
  277. for (Tmp=0;Tmp<256;Tmp++)
  278. {
  279. SrcArray[Tmp] = DestArray[Tmp]+1;
  280. }
  281. SPI_WaitReady();
  282. SPI_SectorErase(0x0000);
  283. SPI_WaitReady();
  284. DrvPDMA_CHEnableTransfer(eDRVPDMA_CHANNEL_1); //使能PDMA通道1
  285. SPI_PageProgram(0);
  286. printf("rogram Flash (Page 0)[Add 1] done!\n");
  287. break;
  288. case 'D':
  289. case 'd':
  290. printf("rogram Flash (Page 0)[Minus 1] ...\n");
  291. SPI_WaitReady();
  292. DrvPDMA_CHEnableTransfer(eDRVPDMA_CHANNEL_0); //使能PDMA通道0
  293. SPI_ReadData(0);
  294. for (Tmp=0;Tmp<256;Tmp++)
  295. {
  296. SrcArray[Tmp] = DestArray[Tmp]-1;
  297. }
  298. SPI_WaitReady();
  299. SPI_SectorErase(0x0000);
  300. SPI_WaitReady();
  301. DrvPDMA_CHEnableTransfer(eDRVPDMA_CHANNEL_1); //使能PDMA通道1
  302. SPI_PageProgram(0);
  303. printf("rogram Flash (Page 0)[Minus 1] done!\n");
  304. break;
  305. default:
  306. printf("请确认您输入的指令是否合法!\n");

  307. }
  308. IsStart = FALSE;
  309. }
  310. }
  311. }

  312. /*****************************
  313. ** Name: SPI_ReadMidDid
  314. ** Function: W25Q16BV读制造商ID及设备ID函数
  315. ** Input: None
  316. ** OutPut: MID & DID
  317. ** Data: 2011-05-07
  318. ** Note:
  319. ****************************/
  320. uint32_t SPI_ReadMidDid(void)
  321. {
  322. uint32_t au32SourceData;
  323. uint32_t au32DestinationData;

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

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

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

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

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

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

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

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


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

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

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

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

  351. return (au32DestinationData & 0xffff);
  352. }

  353. /*****************************
  354. ** Name: SPI_ReadStatusReg1
  355. ** Function: W25Q16BV读状态寄存器1函数
  356. ** Input: None
  357. ** OutPut: ReadStatusReg1
  358. ** Data: 2011-05-07
  359. ** Note:
  360. ****************************/
  361. uint32_t SPI_ReadStatusReg1(void)
  362. {
  363. uint32_t au32SourceData;
  364. uint32_t au32DestinationData;

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

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

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

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

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

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

  378. return (au32DestinationData & 0xFF);
  379. }

  380. /*****************************
  381. ** Name: SPI_WaitReady
  382. ** Function: W25Q16BV忙状态检查函数
  383. ** Input: None
  384. ** OutPut: None
  385. ** Data: 2011-05-07
  386. ** Note:
  387. ****************************/
  388. void SPI_WaitReady(void)
  389. {
  390. uint32_t ReturnValue;

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

  397. /*****************************
  398. ** Name: SPI_ChipErase
  399. ** Function: W25Q16BV片擦除函数
  400. ** Input: None
  401. ** OutPut: None
  402. ** Data: 2011-05-07
  403. ** Note:
  404. ****************************/
  405. void SPI_ChipErase(void)
  406. {

  407. uint32_t au32SourceData;

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

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

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

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

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

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

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

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

  426. DISABLE_SPI_CS;
  427. //从设备片选信号取消激活
  428. }

  429. /*****************************
  430. ** Name: SPI_ReadData
  431. ** Function: W25Q16BV读数据函数
  432. ** Input: StartAddress
  433. ** OutPut: None
  434. ** Data: 2011-05-12
  435. ** Note:
  436. ****************************/
  437. void SPI_ReadData(uint32_t StartAddress)
  438. {
  439. uint32_t au32SourceData;

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

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

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

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

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

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

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

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

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

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

  463. while (1)
  464. {
  465. // 等待 PDMA0 接收结束
  466. if (PDMA0_INT_Flag)
  467. {
  468. PDMA0_INT_Flag = 0;
  469. break;
  470. }
  471. }

  472. DISABLE_SPI_CS;
  473. //从设备片选信号取消激活
  474. }

  475. /*****************************
  476. ** Name: SPI_PageProgram
  477. ** Function: W25Q16BV按页编程函数
  478. ** Input: StartAddress
  479. ** OutPut: None
  480. ** Data: 2011-05-12
  481. ** Note:
  482. ****************************/
  483. void SPI_PageProgram(uint32_t StartAddress)
  484. {
  485. uint32_t au32SourceData;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  518. while (1)
  519. {
  520. // 等待 PDMA1 传输结束
  521. if (PDMA1_INT_Flag)
  522. {
  523. PDMA1_INT_Flag = 0;
  524. break;
  525. }
  526. }

  527. DISABLE_SPI_CS;
  528. //从设备片选信号取消激活
  529. }

  530. /*****************************
  531. ** Name: SPI_SectorErase
  532. ** Function: W25Q16BV扇区擦除函数
  533. ** Input: StartAddress
  534. ** OutPut: None
  535. ** Data: 2011-05-07
  536. ** Note:
  537. ****************************/
  538. void SPI_SectorErase(uint32_t StartAddress)
  539. {

  540. uint32_t au32SourceData;

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

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

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

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

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

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

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

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

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

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

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

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

  568. DISABLE_SPI_CS;
  569. //从设备片选信号取消激活
  570. }
hotpower 发表于 2011-5-13 00:34 | 显示全部楼层
好样的,再谈谈两种方式的差别~~~
 楼主| Swallow_0322 发表于 2011-5-13 07:59 | 显示全部楼层
呵呵!
拿洗衣机打个比方:
    查询方式就相当于老式的洗衣机,加水加洗衣粉放入衣物洗涤,开启电源在那等待到洗涤结束,然后取衣物放入甩干桶,再等待,甩干结束拿出去晾晒;
    PDMA方式就相当于全自动洗衣机,加衣物及洗衣粉,打开电源不管了,去做饭,去玩,爱干啥干啥,听到结束报警声去取出衣物晾干完事,而且洗涤效果优于老式洗衣机。
   比喻也许不恰当,望大叔不要见笑!
hotpower 发表于 2011-5-13 08:58 | 显示全部楼层
比喻的有些怪异,好玩。
pdma是一种数据直接交换。不用cpu干预。
例如本例是内存数据与spi接口的数据交换。它只需你设置好后启动pdma即可,不用你每个字都去存取,特别适于批量操作。
你只需要设置内存地址和spi接口即可。
节省了查询或中断的时间。
 楼主| Swallow_0322 发表于 2011-5-13 17:29 | 显示全部楼层
呵呵!
突发奇想的比喻,表述不是很清楚!(*^__^*) 嘻嘻

我的意思是老式洗衣机每个步骤都需要人工干预而且得等待,而全自动洗衣机放入衣物打开电源就可以干其它事情,无需人工干预,洗衣结束后后告警即PDMA中断提醒操作者操作结束。
ichuangj 发表于 2011-5-17 15:06 | 显示全部楼层
好!马克
fomula 发表于 2011-5-20 00:06 | 显示全部楼层
没调过SPI,想请教nrf24l01这种无线收发模块能用这种PDMA方式吗,直接交换数据,不用CPU干预?
 楼主| Swallow_0322 发表于 2011-5-20 07:43 | 显示全部楼层
我认为这个和你使用的具体芯片无关,只要你使用SPI、ADC、UART或者USB都可以通过PDMA方式进行数据交换!
以上仅为菜鸟的一般理解,如果有误请谅解!
fomula 发表于 2011-5-21 15:41 | 显示全部楼层
谢谢楼上的,我调的试试,调通了nrf24l01的PDMA,放上来共享。
lixupengarm 发表于 2011-5-22 18:49 | 显示全部楼层
mark!!
weshiluwei6 发表于 2011-5-26 13:04 | 显示全部楼层
支持大哥的 MARK 回头学习
564451696 发表于 2011-10-25 09:46 | 显示全部楼层
这个还要顶。。。
huzaizai007 发表于 2012-4-5 16:05 | 显示全部楼层
学习中
yongjun_meng 发表于 2012-5-2 08:42 | 显示全部楼层
谢谢分享
JIESHENGKEJI 发表于 2013-5-7 12:35 | 显示全部楼层
学习中,谢谢分享
sunbingbing 发表于 2013-5-10 07:30 | 显示全部楼层
[em:2:
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

121

主题

1393

帖子

4

粉丝
快速回复 在线客服 返回列表 返回顶部