打印

怎么用DMA实现定时SPI发送

[复制链接]
8421|13
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
video_vb|  楼主 | 2011-12-21 11:36 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
用一个定时器每隔50MS通过DMA触发SPI产生DMA传输一个字节.
也就是说全部用硬件定时发送一个字节,能不能实现?怎么实现?
沙发
video_vb|  楼主 | 2011-12-21 13:14 | 只看该作者
呼叫版主!
我用的是STM32F103

使用特权

评论回复
板凳
香水城| | 2011-12-21 13:19 | 只看该作者
STM32固件库中有不少例程可供参考。

使用特权

评论回复
地板
video_vb|  楼主 | 2011-12-21 13:34 | 只看该作者
只找到单独触发一个DMA的例子,没有一个DMA触发另一个DMA的例子(不用中断)

使用特权

评论回复
5
香水城| | 2011-12-21 13:38 | 只看该作者
不明白,一个DMA触发另一个DMA是什么意思,这是怎么工作的?什么情况下需要这样的工作方式?

使用特权

评论回复
6
video_vb|  楼主 | 2011-12-21 13:57 | 只看该作者
感谢香主。
我需要以固定的速率(5MS一次)上传一个数据到另一个设备,这个数据在缓冲区中,随时会被更改.
CPU有其他的大量频繁的中断需要处理。
我想在不需要CPU干预的情况在后台处理这个数据传输:通过定时器定时启动这个传输过程,不使用中断、不使用查询。

使用特权

评论回复
7
香水城| | 2011-12-21 14:15 | 只看该作者
感谢香主。
我需要以固定的速率(5MS一次)上传一个数据到另一个设备,这个数据在缓冲区中,随时会被更改.
CPU有其他的大量频繁的中断需要处理。
我想在不需要CPU干预的情况在后台处理这个数据传输:通过定时器定时启动 ...
video_vb 发表于 2011-12-21 13:57


你这是一个典型的应用,只需要设置一个定时器,每5ms触发一次DMA,这个DMA操作就是把数据从缓冲区传送到SPI进行发送。这个过程不需要中断也不需要查询,当然更不需要2个DMA。

使用特权

评论回复
8
video_vb|  楼主 | 2011-12-21 15:33 | 只看该作者
我在前面设置了USART DMA和SPI DMA,下面的代码是定时启动哪一个DMA呢,在这搞昏了:

        /* DMA/中断使能寄存器(TIMx_DIER)   
           UDE:更新DMA请求使能 (Update DMA request enable) */
      TIM_DMACmd(TIM7, TIM_DMA_Update, ENABLE);

使用特权

评论回复
9
lxyppc| | 2011-12-21 16:31 | 只看该作者
RM0008中有一张关于DMA和Trigger的表,用什么样的Trigger,启动对应的DMA Channel

使用特权

评论回复
10
lxyppc| | 2011-12-21 16:33 | 只看该作者
楼主这个是典型应用,貌似ST的库里面就有一个一样的代码

使用特权

评论回复
11
video_vb|  楼主 | 2011-12-28 10:46 | 只看该作者
本帖最后由 video_vb 于 2011-12-28 10:49 编辑

试了一下,本来计划每10MS发700个SPI,但实际上只发了一个,为什么呀?

void SPI2_Configuration(u8 sel)
{

  SPI_InitTypeDef SPI_InitStructure;

  SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx;
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
               
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
                  
  SPI_InitStructure.SPI_CRCPolynomial = 7;
  SPI_Init(SPI2, &SPI_InitStructure);

  // Enable SPI2 TXE interrupt
  //SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_TXE, ENABLE);
  
  //SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE);        
  SPI_Cmd(SPI2, ENABLE);

}

// DMA1 channel5 configuration ----------------------------------------------
void DMA_Configuration(void)
{
        DMA_InitTypeDef DMA_InitStructure;
        
        DMA_DeInit(DMA1_Channel5);
        DMA_InitStructure.DMA_PeripheralBaseAddr = SPI2_DR_Address;
        DMA_InitStructure.DMA_MemoryBaseAddr =(u32)Buf;
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
        DMA_InitStructure.DMA_BufferSize = 700;      
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
        DMA_InitStructure.DMA_MemoryInc =  DMA_MemoryInc_Enable; //DMA_MemoryInc_Disable
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
        DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;        //DMA_Mode_Circular;
        DMA_InitStructure.DMA_Priority = DMA_Priority_High;
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
        DMA_Init(DMA1_Channel5, &DMA_InitStructure);


        // Enable DMA1 channel5
        DMA_Cmd(DMA1_Channel5, ENABLE);        
        
        
}

void TIM4_Configuration(void)
{
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  TIM_OCInitTypeDef  TIM_OCInitStructure;

  /* Time base configuration */
  TIM_TimeBaseStructure.TIM_Period = 65535;
  TIM_TimeBaseStructure.TIM_Prescaler = 0;
  TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV2;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;        ////

  TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);

  /* Prescaler configuration */
  TIM_PrescalerConfig(TIM4, 3599, TIM_PSCReloadMode_Immediate);

  /* Output Compare Timing Mode configuration: Channel1 */
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = 200;        //10ms
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

  TIM_OC3Init(TIM4, &TIM_OCInitStructure);
  TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Disable);

  /* TIM IT enable */
  //TIM_ITConfig(TIM4, /*TIM_IT_CC1 | TIM_IT_CC2 |*/ TIM_IT_CC3, ENABLE);
  
  TIM_DMACmd(TIM4, TIM_DMA_CC3, ENABLE);
        
  /* TIM4 enable counter */
  TIM_Cmd(TIM4, ENABLE);
}

void CPU_Configuration(void)
{
  /* System Clocks Configuration */
  RCC_Configuration();
        
  /* NVIC configuration */
  NVIC_Configuration();

  /* Configure the GPIO ports */
  GPIO_Configuration();

  /* USART1 and USART2 configuration ------------------------------------------------------*/
  //USART_Configuration();
  U2_init(2400);
         
  //SPI2
  SPI2_Configuration(0);
   TIM4_Configuration();   
   //DMA
  DMA_Configuration();
   
}

使用特权

评论回复
12
么么么么达| | 2019-10-25 11:35 | 只看该作者
香水城 发表于 2011-12-21 13:19
STM32固件库中有不少例程可供参考。

例子程序在哪个文件夹?我从来没找到~~

使用特权

评论回复
13
香水城| | 2019-11-4 09:52 | 只看该作者
么么么么达 发表于 2019-10-25 11:35
例子程序在哪个文件夹?我从来没找到~~

可能没有针对SPI操作的,回头我尝试做个再跟你交流分享。

使用特权

评论回复
14
香水城| | 2019-11-13 10:21 | 只看该作者
么么么么达 发表于 2019-10-25 11:35
例子程序在哪个文件夹?我从来没找到~~

这里有个应用示例,可以参考之。 STM32定时器触发SPI逐字收发之应用示例

使用特权

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

本版积分规则

个人签名:video_vb@163.com

14

主题

67

帖子

2

粉丝