STM32F103C8T6----ADC+DMA+串口显示

        引言:在进行ADC转换时,如果只采集一个IO的转换,那转换后的数据将会存储在数据寄存器,每转换一次,数据寄存器就被新来的数据覆盖,因此,只进行一个通道转换是没问题的。但如果是多通道转换呢?数据寄存器只会保存最后一个通道转换的数据,因为前面都被覆盖了,串口上所有通道显示的电压值也全是最后一个通道的AD转换数据。所以,DMA传输横空出世了,它的作用是在ADC第一个通道转换完成后第一时间将数据转运出来,防止被下一个通道转运的数据覆盖,把转运后的数据存在一个和通道数数目一样的数组里面就好了,这样,就能第一时间把所有通道数据保留在数组里面,然后用串口一一显示。

        那么啥是DMA呢?就好比你在学校里面自己写作业自己交,CPU就相当于你自己,你不但要自己写作业,还要自己去交,是不是很费时间呢,如果学委帮你把作业去交,你就能省出时间去做更多有意义的事情,学委就好比DMA。总的来说,CPU无时无刻的在进行数据之间的运算、存储、传输,DMA的出现能帮助CPU传输数据,减少CPU的负担。

#include "stm32f10x.h"                  // Device header
#include <stdio.h>

uint16_t AD_Value[2];//定义数据用来存放ADC两个通道转换的数据
int fputc(int ch,FILE *f) //加入这个函数就能使用C语言的printf()打印<stdio.h>
{
	USART_SendData(USART1,ch);
	while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)== RESET);
	return ch;
}

void Adc_Init(void)
{
    /*开启各个外设的时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1|RCC_APB2Periph_GPIOA,ENABLE);
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);//AD特有的分频函数,6分频,就是72/6=12MH
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;//ADC用的是模拟输入模式
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
    /*ADC_RegularChannelConfig(ADCx,通道y,序列z,采样时间),通道:0~17,序列:1~18*/
	ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);
	ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_55Cycles5);
	
	ADC_InitTypeDef ADC_InitStructure;
	ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;//允许连续转换
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//右对齐
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//软件触发
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//独立模式,就是只用ADC1
	ADC_InitStructure.ADC_NbrOfChannel = 2; //2个通道转换
	ADC_InitStructure.ADC_ScanConvMode = ENABLE;//扫描模式,就是扫描多个通道的
	ADC_Init(ADC1,&ADC_InitStructure);
	
	DMA_InitTypeDef DMA_InitStructure;
	DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;//ADC1的数据寄存器地址
	DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//16位半字
	DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设地址不自增
	DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)AD_Value;存储器地址
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;存储器、半字
	DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;存储器地址不自增
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//外设作为传输源
	DMA_InitStructure.DMA_BufferSize = 2;//计数器,一个通道就计一次,这里使用两个通道
	DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//循环模式
	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//非存储器到存储器
	DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//DMA通道响应的优先级设置
	DMA_Init(DMA1_Channel1, &DMA_InitStructure);
	
    /*使能*/
	DMA_Cmd(DMA1_Channel1, ENABLE);
	ADC_DMACmd(ADC1, ENABLE);
	ADC_Cmd(ADC1, ENABLE);
	
    /*ADC数据校准*/
	ADC_ResetCalibration(ADC1);
	while (ADC_GetResetCalibrationStatus(ADC1) == SET);
	ADC_StartCalibration(ADC1);
	while (ADC_GetCalibrationStatus(ADC1) == SET);
	
    /*ADC软件触发*/
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);

}

void Usart1_Init(uint32_t bound)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	
	USART_InitStructure.USART_BaudRate = bound;//波特率
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件流控制
	USART_InitStructure.USART_Mode = USART_Mode_Tx|USART_Mode_Rx;//同时能发送和接收
	USART_InitStructure.USART_Parity = USART_Parity_No;//无检验位
	USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//传输数据宽度:一个字节
	USART_Init(USART1,&USART_InitStructure);
		
	USART_Cmd(USART1,ENABLE);
	USART_ClearFlag(USART1,USART_FLAG_TC);//清除发送标志位
}
void delay(u32 num)//ms延时函数
{
  u16 i,j;
  for(i=0;i<num;i++)
    for(j=0;j<0x800;j++);
}


int main(void)
{
	Adc_Init();
	Usart1_Init(9600);
	while(1)
	{
		/*ADC转换后的数据是整数,最大为4095,要强制转换为float*/
		printf("AD0电压V= %.2f\r\n",(float)AD_Value[0]/4095*3.3);
		printf("AD1电压V= %.2f\r\n",(float)AD_Value[1]/4095*3.3);
		delay(3900);//延时
		
	}
}

 电压转换公式:V=AD转换值/4095*3.3

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蛋骗鸡~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值