图片及文章内容摘自江科大自化协B站视频
前言
这一部分的学习完全不知道原理是很难写好代码的,这篇博客主要通过代码实现的方式叙述,在不需要理解原理的部分直接套用模板代码,按照模板书写容易出错的地方我会加以说明,目的是能在最少时间理解原理的条件下快速的使用STM32。
AD单通道工作源码如下:
一、DMA是什么
Direct Memory Access(存储器直接访问)。这是指一种高速的数据传输操作,允许在外部设备和存储器之间直接读写数据,既不通过CPU,也不需要CPU干预。
二、配置步骤
第一步:RCC开启DMA时钟
第二步:初始化各个参数,包括各站点起始地址,数据宽度,地址是否自增,方向,传输计数器,是否需要自动重装,选择触发源,通道优先级等
第三步:进行开关控制
初始化结束之后,DMA转运还有三个条件,传输计数器大于0,触发源有触发信号,DMA使能。当触发源是软件触发之后将一直会有触发信号。在DMA可以运行之后,每转运一次,传输计数器就自减一次,传输计数器转运为0时自减完成,转运停止
三、代码实现
1.DMA转运模板
MyDMA_Init DMA通道初始化
MyDMA_Transfer 该通道的DMA转运一次
1. #include "stm32f10x.h" // Device header 2. 3. uint16_t MyDMA_Size; 4. 5. void MyDMA_Init(uint32_t AddrA, uint32_t AddrB, uint16_t Size)//初始化函数,参数分别是,源地址,目的地地址,传输次数 6. { 7. MyDMA_Size = Size; 8. 9. RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); 10. 11. DMA_InitTypeDef DMA_InitStructure; 12. DMA_InitStructure.DMA_PeripheralBaseAddr = AddrA;//外设起始地址 13. DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据宽度 14. DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;//外设是否自增 15. DMA_InitStructure.DMA_MemoryBaseAddr = AddrB;//外设起始地址 16. DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//外设数据宽度 17. DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//外设是否自增 18. DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//传输方向 19. DMA_InitStructure.DMA_BufferSize = Size;//缓存区大小,即传输计数器 20. DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;//传输模式,即是否使用自动重装 21. DMA_InitStructure.DMA_M2M = DMA_M2M_Enable;//软件触发还是硬件触发 22. DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//优先级 23. DMA_Init(DMA1_Channel1, &DMA_InitStructure); 24. 25. DMA_Cmd(DMA1_Channel1, DISABLE); 26. } 27. 28. void MyDMA_Transfer(void)//调用一次,转运一次 29. { 30. DMA_Cmd(DMA1_Channel1, DISABLE); 31. DMA_SetCurrDataCounter(DMA1_Channel1, MyDMA_Size);//指定传输计数器的值 32. DMA_Cmd(DMA1_Channel1, ENABLE); 33. 34. while (DMA_GetFlagStatus(DMA1_FLAG_TC1) == RESET); 35. DMA_ClearFlag(DMA1_FLAG_TC1); 36. }
2.AD多通道与DMA
AD_Init 运行后即可持续得到AD各通道的结果
1. #include "stm32f10x.h" // Device header 2. 3. uint16_t AD_Value[4]; 4. 5. void AD_Init(void) 6. { 7. RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); 8. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); 9. RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); 10. 11. RCC_ADCCLKConfig(RCC_PCLK2_Div6); 12. 13. GPIO_InitTypeDef GPIO_InitStructure; 14. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; 15. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3; 16. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 17. GPIO_Init(GPIOA, &GPIO_InitStructure); 18. 19. ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5); 20. ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_55Cycles5); 21. ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_55Cycles5); 22. ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 4, ADC_SampleTime_55Cycles5); 23. 24. ADC_InitTypeDef ADC_InitStructure; 25. ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; 26. ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; 27. ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; 28. ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; 29. ADC_InitStructure.ADC_ScanConvMode = ENABLE; 30. ADC_InitStructure.ADC_NbrOfChannel = 4; 31. ADC_Init(ADC1, &ADC_InitStructure); 32. 33. DMA_InitTypeDef DMA_InitStructure; 34. DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR; 35. DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; 36. DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; 37. DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)AD_Value; 38. DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; 39. DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; 40. DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; 41. DMA_InitStructure.DMA_BufferSize = 4; 42. DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; 43. DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; 44. DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; 45. DMA_Init(DMA1_Channel1, &DMA_InitStructure); 46. 47. DMA_Cmd(DMA1_Channel1, ENABLE); 48. ADC_DMACmd(ADC1, ENABLE); 49. ADC_Cmd(ADC1, ENABLE); 50. 51. ADC_ResetCalibration(ADC1); 52. while (ADC_GetResetCalibrationStatus(ADC1) == SET); 53. ADC_StartCalibration(ADC1); 54. while (ADC_GetCalibrationStatus(ADC1) == SET); 55. 56. ADC_SoftwareStartConvCmd(ADC1, ENABLE); 57. }