我在stm32f103rc中尝试DMA。我按照本教程https://letanphuc.net/2014/06/how-to-use-stm32-dma/编写了自己的代码,使用CMSIS CORE。在这里,我采用了两个阵列,一个来源,一个' sourceArr'我在哪里存储一个随机值并将该数组复制到' destArr'在DMA的帮助下。
DMA相关功能定义和变量
volatile uint32_t status = 0;
uint32_t sourceArr[ARRAYSIZE];
uint32_t destArr[ARRAYSIZE];
#define DMA1_CLOCK_EN() (RCC->AHBENR = RCC_AHBENR_DMA1EN)
#define DMA1_CHANNEL1_EN() (DMA1_Channel1->CCR |= DMA_CCR1_EN) //((uint16_t)0x0001)
void DMA1_Channel1_IRQHandler(void)
{
if (DMA1->ISR & DMA_ISR_TCIF1)
{
status = 1;
Blink_Led(5000);
DMA1->IFCR |= DMA_IFCR_CTCIF1;
}
}
void NVIC_Init()
{
NVIC_EnableIRQ(DMA1_Channel1_IRQn);
NVIC_SetPriority(DMA1_Channel1_IRQn, 0);
}
void DMA_Init(void)
{
DMA1_Channel1->CCR |= DMA_CCR1_MEM2MEM; /*Memory to memory transfer enable ((uint16_t)0x4000)*/
DMA1_Channel1->CCR &= ~DMA_CCR1_CIRC; /* circular mode* ((uint16_t)0x0020) */
/* Priroty set as medium PL[1:0] = 01 */
DMA1_Channel1->CCR |= DMA_CCR1_PL_0; //((uint16_t)0x1000)
/* source and destination data size set as 32bit */
DMA1_Channel1->CCR |= DMA_CCR1_MSIZE_1; //((uint16_t)0x0800)
DMA1_Channel1->CCR |= DMA_CCR1_PSIZE_1; //((uint16_t)0x0200)
/* Auto increment of memory enabled for source and destination */
DMA1_Channel1->CCR |= DMA_CCR1_PINC; //((uint16_t)0x0040)
DMA1_Channel1->CCR |= DMA_CCR1_MINC; //((uint16_t)0x0080)
/* Data transfer direction set as read from peripheral*/
DMA1_Channel1->CCR &= ~DMA_CCR1_DIR; //((uint16_t)0x0010)
/* source and destination start addresses */
DMA1_Channel1->CPAR = (uint32_t)&sourceArr;
DMA1_Channel1->CMAR = (uint32_t)&destArr;
/* Enable DMA1 Channel Transfer Complete interrupt */
DMA1_Channel1->CCR |= DMA_CCR1_TCIE; //((uint16_t)0x0002)
}
void DMA_DeInit(void)
{
DMA1_Channel1->CCR &= (uint16_t)~DMA_CCR1_EN; /* Disable the selected DMAy Channelx */
DMA1_Channel1->CCR = 0; /* Reset DMAy Channelx control register */
DMA1_Channel1->CNDTR = 0; /* Reset DMAy Channelx remaining bytes register */
DMA1_Channel1->CPAR = 0; /* Reset DMAy Channelx peripheral address register */
DMA1_Channel1->CMAR = 0; /* Reset DMAy Channelx memory address register */
DMA1->IFCR |= DMA_IFCR_CGIF1 | DMA_IFCR_CTCIF1 | DMA_IFCR_CHTIF1 | DMA_IFCR_CTEIF1; /* Reset interrupt pending bits for DMA1 Channel1 */
}
主要
int main(void)
{
int i;
for (i=0;i<ARRAYSIZE;i++)
sourceArr[i] = i;
Led_Init();
Blink_Led(1000);
DMA1_CLOCK_EN(); //enable clock for DMA
DMA_DeInit();
DMA_Init();
NVIC_Init();
Blink_Led(1000);
status = 0;
__enable_irq();
DMA1_CHANNEL1_EN(); //Enable DMA1 Channel 1 transfer
while(status==0);
Blink_Led(1000);
for (i=0; i<ARRAYSIZE;i++)
{
destArr[i]=sourceArr[i];
}
Blink_Led(1000);
while (1)
{
}
}
如果一切正常,那么将会有5个闪烁。主函数中有4个,IRQ中有1个。
但我只有两次眨眼。
任何建议都会非常有用。
先谢谢
答案 0 :(得分:3)
您应该设置要传输的数据数
DMA1_Channel1->CNDTR = ARRAYSIZE;
在使用DMA1_CHANNEL1_EN()
。
答案 1 :(得分:2)
感谢大家的帮助。我得到了正确的答案。这是我的错误,因为我忘了设置要传输的数据。工作源代码是
#include "stm32f10x.h"
#define ARRAYSIZE 100
#define LED_PORT_EN() ( RCC->APB2ENR |= RCC_APB2ENR_IOPDEN )
#define LED_PORT GPIOD
#define LED_MODE_BIT1 8
#define LED_MODE_BIT2 9
#define LED_CNF_BIT1 10
#define LED_CNF_BIT2 11
#define CNF_SET_PORTD(BIT1,BIT2) ( LED_PORT->CRL &= ~((1<<BIT1) | (1<<BIT2)) ) //General purpose output push-pull
#define MODE_SET_PORTD(BIT1,BIT2) ( LED_PORT->CRL |= (1<<BIT1) | (1<<BIT2) ) //Output mode, max speed 50 MHz.
#define SET_GPIO_BIT_PORTD(BIT) ( LED_PORT->BSRR = (1 << BIT) ) //For setting the Bit
#define RESET_GPIO_BIT_PORTD(BIT) ( LED_PORT->BSRR = ( (1 << BIT) << 16 ) ) //For Resseting Bit
volatile uint32_t status = 0;
uint32_t sourceArr[ARRAYSIZE];
uint32_t destArr[ARRAYSIZE];
#define DMA1_CLOCK_EN() (RCC->AHBENR |= RCC_AHBENR_DMA1EN)
#define DMA1_CHANNEL1_EN() (DMA1_Channel1->CCR |= DMA_CCR1_EN) //((uint16_t)0x0001)
void Delay(int ms);
void Led_Init(void);
void Blink_Led(int ms);
void DMA_DeInit(void);
void DMA_Init(void);
void NVIC_Init(void);
void DMA1_Channel1_IRQHandler(void);
int main(void)
{
int i;
for (i=0;i<ARRAYSIZE;i++)
sourceArr[i] = i;
Led_Init();
Blink_Led(1000);
DMA1_CLOCK_EN(); //enable clock for DMA
DMA_DeInit();
DMA_Init();
NVIC_Init();
Blink_Led(1000);
status = 0;
__enable_irq();
DMA1_CHANNEL1_EN(); //Enable DMA1 Channel 1 transfer
while(status==0);
Blink_Led(1000);
for (i=0; i<ARRAYSIZE;i++)
{
destArr[i]=sourceArr[i];
}
Blink_Led(1000);
while (1)
{
}
}
void DMA1_Channel1_IRQHandler(void)
{
if (DMA1->ISR & DMA_ISR_TCIF1)
{
status = 1;
Blink_Led(5000);
DMA1->IFCR |= DMA_IFCR_CTCIF1;
}
}
void NVIC_Init()
{
NVIC_EnableIRQ(DMA1_Channel1_IRQn);
NVIC_SetPriority(DMA1_Channel1_IRQn, 0);
}
void DMA_Init(void)
{
DMA1_Channel1->CCR |= DMA_CCR1_MEM2MEM; /*Memory to memory transfer enable ((uint16_t)0x4000)*/
DMA1_Channel1->CCR &= ~DMA_CCR1_CIRC; /* circular mode* ((uint16_t)0x0020) */
/* Priroty set as medium PL[1:0] = 01 */
DMA1_Channel1->CCR |= DMA_CCR1_PL_0; //((uint16_t)0x1000)
/* source and destination data size set as 32bit */
DMA1_Channel1->CCR |= DMA_CCR1_MSIZE_1; //((uint16_t)0x0800)
DMA1_Channel1->CCR |= DMA_CCR1_PSIZE_1; //((uint16_t)0x0200)
/* Auto increment of memory enabled for source and destination */
DMA1_Channel1->CCR |= DMA_CCR1_PINC; //((uint16_t)0x0040)
DMA1_Channel1->CCR |= DMA_CCR1_MINC; //((uint16_t)0x0080)
/* Data transfer direction set as read from peripheral*/
DMA1_Channel1->CCR &= ~DMA_CCR1_DIR; //((uint16_t)0x0010)
/*size of data to be transfered*/
DMA1_Channel1->CNDTR = ARRAYSIZE;
/* source and destination start addresses */
DMA1_Channel1->CPAR = (uint32_t)sourceArr;
DMA1_Channel1->CMAR = (uint32_t)destArr;
/* Enable DMA1 Channel Transfer Complete interrupt */
DMA1_Channel1->CCR |= DMA_CCR1_TCIE; //((uint16_t)0x0002)
}
void DMA_DeInit(void)
{
DMA1_Channel1->CCR &= (uint16_t)~DMA_CCR1_EN; /* Disable the selected DMAy Channelx */
DMA1_Channel1->CCR = 0; /* Reset DMAy Channelx control register */
DMA1_Channel1->CNDTR = 0; /* Reset DMAy Channelx remaining bytes register */
DMA1_Channel1->CPAR = 0; /* Reset DMAy Channelx peripheral address register */
DMA1_Channel1->CMAR = 0; /* Reset DMAy Channelx memory address register */
DMA1->IFCR |= DMA_IFCR_CGIF1 | DMA_IFCR_CTCIF1 | DMA_IFCR_CHTIF1 | DMA_IFCR_CTEIF1; /* Reset interrupt pending bits for DMA1 Channel1 */
}
/** @breif: For wait and doing nothing i.e for delay
* @param: delaya time
* @retVal: None
*/
void Delay(int ms)
{
int i,j;
for (i = 0; i < ms; ++i) {
for (j = 0; j < 5000; ++j);
}
}
/** @breif: Initalize GPIO For Led
* @param: None
* @retVal: None
*/
void Led_Init()
{
LED_PORT_EN(); //Enable RCC for Led Port
CNF_SET_PORTD(LED_CNF_BIT1,LED_CNF_BIT2); //SET CNF General purpose output push-pull
MODE_SET_PORTD(LED_MODE_BIT1,LED_MODE_BIT2); //SET MODE Output mode, max speed 50 MHz.
}
/** @breif: Blink Led Placed in PORT D Pin 2
* @param: Delay for each state(ON/OFF)
* @retVal: None
*/
void Blink_Led(int ms)
{
RESET_GPIO_BIT_PORTD(2); //Make Led High
Delay(ms); //wait
SET_GPIO_BIT_PORTD(2); //Make Led Low
Delay(ms); //wait
}
谢谢大家。