打印
[技术问答]

关于N32905的SPI的DMA问题

[复制链接]
2026|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
凌福义|  楼主 | 2015-4-25 16:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我使用PDMA和SPI和下位通信,但是下位机总是只能接收到1个数据,谁能帮忙看下代码


//===================================================================
// File Name : spi.c
// Function  : SPI通讯驱动
// By            : lfy
// Date      : 04, 10, 2015
// Version   : 0.0
// History         :       
//===================================================================
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
//=======================
//#include    "core/includes.h"               /* uC/OS interface */
#include "ucos_ii.h"
//=======================
#include "lcd.h"
#include "smdong.h"
#include "sm.h"
#include "smgn1.h"
#include "glib.h"
#include "smpage.h"
#include "HmiStart.h"
#include "def.h"
#include "initmain.h"
#include "smHzk16.h"
#include "math.h"
#include "usbin.h"
#include "MsgShow.h"

#include "DataTransmissionC.h"
#include "Timer.h"
#include "Macro_File.h"
#include "UpLoadRecipeData.h"
#include "Penetrate.h"  
#include "rtc.h"
#include "w55fa93_gpio.h"
#include "DrvEDMA.h"
#include "common.h"
#include "spi.h"
/*****************************************************************
SPI发送完成需要接收必须发送RX_COUNT个填充字节为从机提供CLK
例如可以发送:0xff
******************************************************************/
/********************************************************/
/*************下面是SPI的DMA数据结构***********************/
/********************************************************/
#define SPI_MAX_LENTH   8  //最大一次接收发送1K
#define SPI_TX_BASE     (U32)(&SPI0_TX0)
#define SPI_RX_BASE     (U32)(&SPI0_RX0)

/***************SPI发送错误码**************************/
#define SPI0_Right           0
#define SPI0_LenthError      1
#define SPI0_Busy           2
/*****************************************/

U8 SPI0_DMA_TX[SPI_MAX_LENTH]={0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08}; //DMA发送内存池
U8 SPI0_DMA_RX[SPI_MAX_LENTH]; //DMA接收内存池




struct spi0 *SPI0;

static void EDMA_CH1_Enable(void)
{
    PDMA_CSR1|=(1<<0);
}

static void EDMA_CH1_Disable(void)
{
    PDMA_CSR1&=~(1<<0);
}


void EDMA_IRQHandler(void)
{
    u8 tmp=0;
    PDMA_ISR|=1<<1;
    #if 0
    if(SPI0->RW_Count < SPI0->RW_Lenth)
    {     
        if(SPI0->IfWrRe==2)//读从设备
        {
            SPI0_DMA_RX[SPI0->RW_Count]=SPI0_RX0;
        }   
        sysprintf("C\r\n");
        SPI0->RW_Count+=1;
        PDMA_CSR1|=(1<<23);
        SPI0_EDMA|=(1<<0);
    }
    else
    {
        if(SPI0->IfWrRe==2)//读从设备
        {
            SPI0->Recive_Finish=1;//接收完成
        }
        PDMA_CSR1|=(1<<1); //Soft Reset
        SPI0->IfWrRe=0;//读写和计数值复位
        SPI0->RW_Count=0;
    }
    #endif
  
   {
       EDMA_CH1_Disable();
   }
   
}




/*===================================================================
SPI读取从设备一般流程:
    1:确定读取长度SPI0->RW_Lenth,注意不要超过设定最大值
    2:OS轮询SPI0->Recive_Finish是否为1,则表示读取完成
    3:调用SPI_Read,查看返回值,返回right表示读取成功,但并不表示读取完成
      读取错误对应不同错误代码
    4:轮询到SPI0->Recive_Finish=1即可从SPI0_DMA_RX[SPI_MAX_LENTH]取出数据
      即可
====================================================================*/

u8 SPI_Read(void)
{
   if(SPI0->RW_Lenth>SPI_MAX_LENTH)//大于约束长度
   {
        return SPI0_LenthError;
   }
   if(SPI0->IfWrRe==1)//正在写
   {
        return SPI0_Busy;
   }
   SPI0->IfWrRe=2;
   SPI0->RW_Count=0;
   PDMA_CSR1|=(1<<1); //Reset Point
   PDMA_BCR=SPI0->RW_Lenth;    //Lenth
   PDMA_CSR1|=(1<<23);          //Start DMA
   SPI0_EDMA|=(1<<0);   
   return SPI0_Right;       //此次返回值只代表发送执行,并不代表发送完成
}

/*===================================================================
SPI写从设备一般流程:
    1:确定写入长度SPI0->RW_Lenth,注意不要超过设定最大值
    2:对SPI0_DMA_TX[SPI_MAX_LENTH]进行赋值,注意格式为U8
    3:调用SPI_Write,查看返回值,返回right表示写入成功,但并不表示写入完成
      写入错误对应不同错误代码
====================================================================*/

u8 SPI_Write(void)
{
   SPI0->RW_Lenth=8;
   if(SPI0->RW_Lenth>SPI_MAX_LENTH)//大于约束长度
   {
        return SPI0_LenthError;
   }
   if(SPI0->IfWrRe==2)//正在读
   {
        return SPI0_Busy;
   }
   SPI0_EDMA&=~(1<<1);//write
   PDMA_CSR1|=(1<<1); //Soft Reset
   
   SPI0->IfWrRe=1;
   SPI0->RW_Count=0;
   PDMA_BCR=SPI0->RW_Lenth;    //Lenth
   
   PDMA_CSR1|=(1<<23);          //Start DMA
   SPI0_EDMA|=(1<<0);   
   return SPI0_Right;       //此次返回值只代表发送执行,并不代表发送完成
}






void SPI0_PDMA_Init(void)
{
        /*****************PDMA发送初始化,目的地址为TX0,源地址为内存池***********************/
    PDMA_CSR1|=(1<<8);
    PDMA_CSR1&=~(1<<8);//Rest DMA CH1
    EDSSR|=(7<<0);
    EDSSR&=~(7<<16);
    SPI0_PDMACLK_ENABLE; //Enable CH1 CLK  
    PDMA_CSR1|=(1<<1); //Soft Reset
    PDMA_CSR1|=(1<<0);
    PDMA_CSR1|=(1<<19); //Width 8 bit
    PDMA_CSR1|=(1<<3); //MEN--->APB
    PDMA_SAR=(U32)SPI0_DMA_TX;//Source Address
    PDMA_DAR=(U32)SPI_TX_BASE; //Direction Address
    PDMA_CSR1|=(3<<4); //Source Address INC
    PDMA_CSR1|=(1<<7); //Dir Address Fixed
    PDMA_BCR=SPI_MAX_LENTH;
   
    PDMA_CSR1|=(1<<12);
    PDMA_IER|=1<<2;//使能传输完成和读写异常中断  
    PDMA_ISR|=1<<1;
    PDMA_ISR|=1<<0;
    sysInstallISR(IRQ_LEVEL_1,  IRQ_EDMA, (PVOID)EDMA_IRQHandler);
    sysEnableInterrupt(IRQ_EDMA);   
   
    /*****************PDMA发送初始化,目的地址为TX0,源地址为内存池***********************/

}

/*SYS_CLK=192MHZ , HCLK=96MHZ , PCLK=48MHZ*/
u8 SPI_Init(void)
{
    U16 dat;
    //delayy1(1000);delayy1(1000);delayy1(1000);delayy1(1000);delayy1(1000);
    /*
    GPIOD_12----SPI_CLK
    GPIOD_13----SPI_CS
    GPIOD_14----SPI_MISO
    GPIOD_15----SPI_MOSI
   
        打开内部上拉电阻,外部无上拉
        */
    GPIOD_PUEN|=((1<<15)|(1<<14)|(1<<13)|(1<<12));
    GPIOD_FUN&=~((3<<30)|(3<<28)|(3<<26)|(3<<24));
    GPIOD_FUN|=((2<<30)|(2<<28)|(2<<26)|(2<<24));
    GPIOD_OMD&=~(1<<14);//MISO
    GPIOD_OMD|=(1<<12);//CLK
    GPIOD_OMD|=(1<<13);//CS
    GPIOD_OMD|=(1<<15);//MOSI
    SPI0_CLK_ENABLE;//时钟使能
    SPI0_SSR&=~(1<<2);//CS低电平片选
   
    SPI0_CNTRL&=~(1<<18);//SPI_Master
    SPI0_CNTRL&=~(1<<10);;//MSB Frist
    SPI0_CNTRL|=(1<<2);//Tx信号在时钟下降沿改变
    SPI0_CNTRL&=~(1<<1);//Rx信号在上升沿锁存//
    SPI0_CNTRL&=~(3<<8);//1次传输1字节
   
    SPI0_CNTRL|=(8<<3);//一次传输8bit

    /*CLK=fPCLK/((DIV+1)*2)*/
    SPI0_DIVIDER&=0xffff0000;
    SPI0_DIVIDER|=1;//clk=48M/(2*2)=12M
    SPI0_SSR &= ~(1<<3); //Slave Select non-auto  

    SPI0_PDMA_Init();
    /*SPI参数复位*/
    SPI0->Recive_Finish=0;
    SPI0->IfWrRe=0;
    SPI0->RW_Count=0;
   
        dat=SPI_Write();
    sysprintf("dat=%d\r\n",dat);
    while(1);

}

沙发
稳稳の幸福| | 2015-4-25 16:54 | 只看该作者
楼主检查发完一个之后干了什么,然后才能确定为何只发了一个。

使用特权

评论回复
板凳
yiyigirl2014| | 2015-5-26 20:52 | 只看该作者
接收完进行复位了吗,还是怎么回事,卡死在哪儿了。

使用特权

评论回复
地板
643757107| | 2015-5-27 20:24 | 只看该作者
楼主搞定后也没来告诉大家啊,看来楼主掌握精髓了。

使用特权

评论回复
5
xinba0625| | 2015-5-28 16:34 | 只看该作者
点击链接加入群【Nuvoton   N329xx】:http://jq.qq.com/?_wv=1027&k=eKJWh5

使用特权

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

本版积分规则

4

主题

14

帖子

0

粉丝