文章目录
- 前言
- 一、ADC配置修改
- 二、配置DMA
- 三、DMA中断
- 四、完整参考代码
- 总结
前言
提示:这里可以添加本文要记录的大概内容:
项目需要:
在原有基础上改进,采用DMA中断采集数据
提示:以下是本篇文章正文内容,下面案例可供参考
一、ADC配置修改
1.启动连续转换
2.开启ADC-DMA通道
/* 使能ADC1对应的DMA */
ADC_DMACmd(ADC1, ENABLE);
在这里插入代码片
二、配置DMA
1.确定DMA的通道 ADC1 在DMA的通道1
u16 ADCConvertedValue;
#define ADC1_DR_Address ((uint32_t)0x40012400+0x4C)//ADC数据外设基地址
// * @返回值:无
// */
void DMA_ADC_Configure(void)
{
/* 定义DMA初始化结构体 */
DMA_InitTypeDef DMA_InitStructure;
/* 打开DMA时钟 */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
/* 外设基地址 */
DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
/* RAM基地址 */
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADCConvertedValue;
/* 传输方向,外设为源地址 */
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
/* 缓冲区大小,即一次传输的数据量,范围0~65536,此处为1 */
DMA_InitStructure.DMA_BufferSize = 1;
/* 外设和RAM地址不自增 */
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
/*外设和RAM数据宽度,AD为12位,因此宽度为半字(16位)*/
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
/* 传输模式,循环传送 */
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
/* 优先级高 */
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
/* 非内存到内存传输 */
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
/* 完成配置 */
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
/* 允许传输完成中断 */
DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);
/* 开启DMA */
DMA_Cmd(DMA1_Channel1, ENABLE);
}
三、DMA中断
开启中断只能仿真,实际不能使用
因为进入中断的频率太高了,导致没时间运行主函数
/**
* @简介:DMA1通道1中断服务程序
* @参数: 延时毫秒数
* @返回值:无
*/
void DMA1_Channel1_IRQHandler(void)
{
/* 检测DMA1 Channel1 传输完成中断 */
if(DMA_GetITStatus(DMA1_IT_TC1))
{
/* 传输完成标志置1 */
DMA_ADC_OK = 1;
/* 清除中断 */
DMA_ClearITPendingBit(DMA1_IT_GL1);
}
}
四、完整参考代码
#include "stm32f10x.h"
#include "stdio.h"
__IO uint16_t ADCConvertedValue;
u8 DMA_ADC_OK;
/**
* @brief 微秒级延时
* @param xus 延时时长,范围:0~233015
* @retval 无
*/
void Delay_us(uint32_t xus)
{
SysTick->LOAD = 72 * xus; //设置定时器重装值
SysTick->VAL = 0x00; //清空当前计数值
SysTick->CTRL = 0x00000005; //设置时钟源为HCLK,启动定时器
while(!(SysTick->CTRL & 0x00010000)); //等待计数到0
SysTick->CTRL = 0x00000004; //关闭定时器
}
/**
* @brief 毫秒级延时
* @param xms 延时时长,范围:0~4294967295
* @retval 无
*/
void Delay_ms(uint32_t xms)
{
while(xms--)
{
Delay_us(1000);
}
}
/**
* @brief 秒级延时
* @param xs 延时时长,范围:0~4294967295
* @retval 无
*/
void Delay_s(uint32_t xs)
{
while(xs--)
{
Delay_ms(1000);
}
}
void adc1_init()
{
u16 adc_temp;
ADC_InitTypeDef ADC_InitStruct;
GPIO_InitTypeDef GPIO_InitStruct;
//1.开启时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1|RCC_APB2Periph_GPIOA,ENABLE);
RCC_ADCCLKConfig(RCC_PCLK2_Div6);// 72/6=12
//2.配置引脚 PA0为模拟输入
GPIO_InitStruct.GPIO_Pin= GPIO_Pin_0|GPIO_Pin_1; // 通道0 和通道1
GPIO_InitStruct.GPIO_Speed= GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &GPIO_InitStruct); //&x
ADC_InitStruct.ADC_ContinuousConvMode= ENABLE;//启动连续转换
ADC_InitStruct.ADC_DataAlign=ADC_DataAlign_Right;
ADC_InitStruct.ADC_ExternalTrigConv= ADC_ExternalTrigConv_None;
ADC_InitStruct.ADC_Mode= ADC_Mode_Independent;
ADC_InitStruct.ADC_NbrOfChannel= 1;
ADC_InitStruct.ADC_ScanConvMode= ENABLE;
ADC_Init(ADC1, &ADC_InitStruct);
/* 使能ADC1对应的DMA */
ADC_DMACmd(ADC1, ENABLE);
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_1Cycles5);
ADC_Cmd(ADC1, ENABLE);
// 复位和校准ADC
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1)); //为0说明复位完成
ADC_StartCalibration(ADC1);
while( ADC_GetCalibrationStatus( ADC1)); //为0说明校准完成
// 软件触发转换 等待转换完成
ADC_SoftwareStartConvCmd( ADC1, ENABLE);
while(!ADC_GetFlagStatus( ADC1, ADC_FLAG_EOC) );
adc_temp=ADC_GetConversionValue(ADC1);
printf("ADC的电压为 %d \r\n",adc_temp);
}
#define ADC1_DR_Address ((uint32_t)0x40012400+0x4C)//ADC数据外设基地址
// * @返回值:无
// */
void DMA_ADC_Configure(void)
{
/* 定义DMA初始化结构体 */
DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* 打开DMA时钟 */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
/* 外设基地址 */
DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
/* RAM基地址 */
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADCConvertedValue;
/* 传输方向,外设为源地址 */
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
/* 缓冲区大小,即一次传输的数据量,范围0~65536,此处为1 */
DMA_InitStructure.DMA_BufferSize = 1;
/* 外设和RAM地址不自增 */
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
/*外设和RAM数据宽度,AD为12位,因此宽度为半字(16位)*/
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
/* 传输模式,循环传送 */
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
/* 优先级高 */
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
/* 非内存到内存传输 */
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
/* 完成配置 */
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
/* 允许传输完成中断 */
DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);
/* 开启DMA */
DMA_Cmd(DMA1_Channel1, ENABLE);
// /* 允许DMA中断 */
// NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
// NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
// NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
// NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
// NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
// NVIC_Init(&NVIC_InitStructure);
}
void usart1_init()
{
//PA9 TX PA10 RX USART1
GPIO_InitTypeDef GPIO_InitStruct;
USART_InitTypeDef USART_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1, ENABLE);//1.开时钟
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_9;//发送
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_10;//接收
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);
USART_InitStruct.USART_BaudRate=115200;
USART_InitStruct.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
USART_InitStruct.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;
USART_InitStruct.USART_Parity=USART_Parity_No;
USART_InitStruct.USART_StopBits=USART_StopBits_1;
USART_InitStruct.USART_WordLength=USART_WordLength_8b;
USART_Init(USART1, &USART_InitStruct);//2.初始化串口
USART_Cmd(USART1, ENABLE);//3.是能串口
USART_SendData(USART1, '4');
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE)!=1);
USART_SendData(USART1, '1');
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE)!=1);
USART_SendData(USART1, 0X41);
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE)!=1);
USART_SendData(USART1, 41);
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE)!=1);
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE );// 4.接受完成中断
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 5.配置中断分组
NVIC_InitStruct.NVIC_IRQChannel=USART1_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority=0;
NVIC_Init(&NVIC_InitStruct);//配置中断优先级
}
int fputc(int ch,FILE *f)
{
USART_SendData(USART1, (u8)ch);
while(!USART_GetFlagStatus(USART1, USART_FLAG_TXE));
return ch;
}
u16 ADC_channel_0()
{
u16 temp;
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_1Cycles5);
// 软件触发转换 等待转换完成
ADC_SoftwareStartConvCmd( ADC1, ENABLE);
while(!ADC_GetFlagStatus( ADC1, ADC_FLAG_EOC) );
temp=ADC_GetConversionValue(ADC1);
return temp;
}
u16 ADC_channel_1()
{
u16 temp;
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_1Cycles5);
// 软件触发转换 等待转换完成
ADC_SoftwareStartConvCmd( ADC1, ENABLE);
while(!ADC_GetFlagStatus( ADC1, ADC_FLAG_EOC) );
temp=ADC_GetConversionValue(ADC1);
return temp;
}
//ch:通道值 0~3
u16 Get_Adc(u8 ch)
{
//设置指定ADC的规则组通道,一个序列,采样时间
ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 ); //ADC1,ADC通道,采样时间为239.5周期
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束
return ADC_GetConversionValue(ADC1); //返回最近一次ADC1规则组的转换结果
}
u16 Get_Adc_Average(u8 ch,u8 times)
{
u32 temp_val=0;
u8 t;
for(t=0;t<times;t++)
{
temp_val+=Get_Adc(ch);
Delay_ms(5);
}
return temp_val/times;
}
int main()
{
u16 ad_temp;
usart1_init();
printf("串口初始化成功 \r\n");
adc1_init();//复位一次读取一次电压
DMA_ADC_Configure();
while(1)
{
if(DMA_ADC_OK || 1)
{
printf("ADC_channel_0的电压为 %d \r\n",ADCConvertedValue);
DMA_ADC_OK=0;
Delay_ms(1000);
}
// ad_temp=ADC_channel_0();
//
// printf("ADC_channel_0的电压为 %d \r\n",ad_temp);
// ad_temp=ADC_channel_1();
//
// printf("ADC_channel_1的电压为 %d \r\n",ad_temp);
}
}
/**
* @简介:DMA1通道1中断服务程序
* @参数: 延时毫秒数
* @返回值:无
*/
void DMA1_Channel1_IRQHandler(void)
{
/* 检测DMA1 Channel1 传输完成中断 */
if(DMA_GetITStatus(DMA1_IT_TC1))
{
/* 传输完成标志置1 */
DMA_ADC_OK = 1;
/* 清除中断 */
DMA_ClearITPendingBit(DMA1_IT_GL1);
}
}
//#include "stm32f10x.h"
//int main(void)
//{
1.//时钟
2.//功能配置
// //LED0 PA8
// // sbit led0=P1^0;
//
// /*
//
//1. PC5 上拉输入
//2. 时钟
//3.数据寄存器
//
//
//
// */
//
// GPIO_InitTypeDef GPIO_InitStructure;
//
// RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD, ENABLE);
// GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8;
// GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
// GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
// GPIO_Init(GPIOA, & GPIO_InitStructure);
//
// GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2;
// GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
// GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
// GPIO_Init(GPIOD, & GPIO_InitStructure);
// //key0
// GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;
// GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
// GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
// GPIO_Init(GPIOC, & GPIO_InitStructure);
//
// //key1
// GPIO_InitStructure.GPIO_Pin=GPIO_Pin_15;
// GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
// GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
// GPIO_Init(GPIOA, & GPIO_InitStructure);
//
// while(1)
// {
// if(GPIO_ReadInputDataBit( GPIOC, GPIO_Pin_5)==0)
// {
//
// GPIO_ResetBits(GPIOA, GPIO_Pin_8); //亮
//
// }
// else
// {
// GPIO_SetBits(GPIOA, GPIO_Pin_8);//灭
//
//
// }
// if(GPIO_ReadInputDataBit( GPIOA, GPIO_Pin_15)==0)
// {
//
//
// GPIO_ResetBits(GPIOD, GPIO_Pin_2);
// }
// else
// {
//
// GPIO_SetBits(GPIOD, GPIO_Pin_2);
//
// }
//
//
//
// }
//}
未完,持续更新中
总结
学习使人快乐!
音乐使人愉悦!
日积月累使人充实和自信!