DMA传输:
原理:DMA 传输将数据从一个地址空间复制到另外一个地址空间。
DMA传输数据,但是不需要占用MCU,即在传输数据时,MCU可以做别的事,像多线程。数据传输从外设到存储器或者从存储器到存储器。DMA控制器包含了DMA1和DMA2,其中DMA1有7个通道,DMA2有5个通道,可以理解为传输数据的一种管道。要注意的是,DMA2只存在于大容量单片机中。
工作过程:
1.DMA请求
如果外设想通过DMA传输数据,必须先向DMA控制器发送DMA请求,DMA收到请求信号后,控制器会给外设一个应答信号,当外设应答且DMA控制器收到应答信号后,就会启动DMA传输,直到传输完毕。
DMA有DMA1和DMA2两个控制器,DMA1有两个控制器,DMA1有7个通道,DMA2有5个通道,不同DMA控制器的通道有不同的外设请求。
2、通道
DMA有12个独立可编程的通道,DMA1有7个通道,DMA2有5个通道,每个通道对应不同外设的DMA请求。虽然每个通道可以接收多个外设请求,但是同一时间只能接收一个,不能同时接收多个。
3、仲裁器
当同时有多个DMA请求时,就意味着有先后响应的问题,这个就由仲裁器管理。仲裁器管理DMA请求分为2个阶段:第一阶段属于软件阶段,可以在MDA_CCRx寄存器中设置,有 4 个等级:非常高、高、中和低四个优先级。第二阶段属于硬件阶段,如果两个或以上的DMA 通道请求设置的优先级一样,则他们优先级取决于通道编号,编号越低优先权越高,比如通道 0 高于通道 1。在大容量产品和互联型产品中,DMA1 控制器拥有高于 DMA2 控制器的优先级。
配置:
DMA_ InitTypeDef 初始化结构体
typedef struct
{
uint32_t DMA_PeripheralBaseAddr; // 外设地址 uint32_t
DMA_MemoryBaseAddr; // 存储器地址 uint32_t
DMA_DIR; // 传输方向 uint32_t
DMA_BufferSize; // 传输数目 uint32_t
DMA_PeripheralInc; // 外设地址增量模式 uint32_t
DMA_MemoryInc; // 存储器地址增量模式 uint32_t
DMA_PeripheralDataSize; // 外设数据宽度 uint32_t
DMA_MemoryDataSize; // 存储器数据宽度 uint32_t
DMA_Mode; // 模式选择 uint32_t
DMA_Priority; // 通道优先级 uint32_t
DMA_M2M; // 存储器到存储器模;
}DMA_Init TypeDef;
DMA数据配置:
void DMA_Config(void)
{
DMA_InitTypeDef DMA_InitStructure;
RCC_AHBPeriphClockCmd(DMA_CLOCK, ENABLE);// 开启 DMA 时钟
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)aSRC_Const_Buffer;// 源数据地址
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)aDST_Buffer;// 目标地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; // 方向:外设到存储器(这里是内部的 FLASH)
DMA_InitStructure.DMA_BufferSize = BUFFER_SIZE; // 传输大小
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable; // 外设(内部的 FLASH)地址递增
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; // 内存地址递增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; // 外设数据单位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; // 内存数据单位
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ; // DMA 模式,一次或者循环模式
//DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High; // 优先级:高
DMA_InitStructure.DMA_M2M = DMA_M2M_Enable; // 使能内存到内存的传输
DMA_Init(DMA_CHANNEL, &DMA_InitStructure); // 配置 DMA 通道
DMA_Cmd(DMA_CHANNEL,ENABLE); // 使能 DMA
}
调用 RCC_AHBPeriphClockCmd 函数开启 DMA时钟,使用 DMA控制器之前必须开启对应的时钟。 源地址和目标地址使用之前定义的数组首地址,传输的数据量为宏BUFFER_SIZE 决定,源和目标地址指针地址递增,使用一次传输模式不能循环传输,因为只有一个 DMA通道,优先级随便设置,最后调用 DMA_Init 函数完成 DMA 的初始化配置。
DMA_ClearFlag函数用于清除DMA标志位,代码用到传输完成标志位,使用之前先清除传输完成标志位以免产生不必要干扰。DMA_ClearFlag 函数需要 1 个形参,即事件标志位,可选有传输完成标志位、半传输标志位、FIFO 错误标志位、传输错误标志位等等,非常多,我们这里选择传输完成标志位,由宏DMA_FLAG_TC 定义。
DMA_Cmd 函数用于启动或者停止 DMA 数据传输,它接收两个参数,第一个是 DMA通道,另外一个是开启 ENABLE 或者停止 DISABLE。
主要完成任务:
1、FOC2.0程序进行细致的梳理;
2、起动的检测采样的细致过程有了更深的理解;
3、对ADC采样时的扇区判断,及其注入方式的程序书写进行更深的了解。
总的来说,FOC2.0 无霍尔控制方式的BLDC电机运行程序已经大致掌握,但应该还有些细节还未发掘。
接下来,用 有霍尔控制的电机运行程序 来再次深入学习 FOC2.0
上一篇:【STM32电机矢量控制】记录12——IWDG看门狗
下一篇:【STM32电机矢量控制】记录9——状态观测器与锁相环
推荐阅读最新更新时间:2024-03-16 16:14