【32单片机学习】(10)STM32串口+内部温度传感器+光敏传感器通过DMA搬运数据

目录

前言

一、DMA及各外设介绍

二、实验现象

串口发送

LCD显示

三、代码部分

1.adc部分

adc.c

         adc.h

2.串口部分

serial.c

serial.h

3.DMA配置

dma.c

dma.h

4.main函数

main.c

总结


前言

基于stm32f103zet6,将串口收发不定长数据和adc采集通过使用dma搬运数据,提高单片机cpu的运行效率,加深对dma和adc功能的学习。


一、DMA及各外设介绍

可以参考之前文章,这里只贴出相关代码。

【32单片机学习】(6)STM32串口+DMA收发不定长数据_dma 不定长数据的收发_Godox_user的博客-CSDN博客

二、实验现象

串口发送

LCD显示

三、代码部分

1.adc部分

adc.c

这里使用的是ADC1的通道16,stm32内部自带的温度传感器

ADC3的通道6,在GPIOF_PIN_8上接的光敏传感器

由于是ADC1和ADC3两个不同组ADC,所以要分开单独进行测量,当ADC1中有多个ADC设备时,可以打开连续扫描模式。

#include "adc.h"
#include "delay.h"
#include "serial.h"

uint16_t AD_Value1[1],AD_Value2[1];

void Adc_Init(void)
{
    
    ADC_InitTypeDef ADC_InitStructure;
    ADC_InitTypeDef ADC_InitStructure1;     
    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF | RCC_APB2Periph_ADC1| RCC_APB2Periph_ADC3, ENABLE );	  //使能ADC1通道时钟

    RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M
                         
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;		//模拟输入引脚
    GPIO_Init(GPIOF, &GPIO_InitStructure);	
    
    ADC_DeInit(ADC1);  //复位ADC1 
    ADC_DeInit(ADC3);  //复位ADC1 
    
    
    ADC_TempSensorVrefintCmd(ENABLE); //开启内部温度传感器
    
    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;	//ADC工作模式:ADC1和ADC2工作在独立模式
    ADC_InitStructure.ADC_ScanConvMode = DISABLE;	//模数转换工作在单通道模式
    ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;	//模数转换工作在单次转换模式
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;	//转换由软件而不是外部触发启动
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;	//ADC数据右对齐
    ADC_InitStructure.ADC_NbrOfChannel = 1;	//顺序进行规则转换的ADC通道的数目
    ADC_Init(ADC1, &ADC_InitStructure);	//根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器 
    
    
    ADC_InitStructure1.ADC_Mode = ADC_Mode_Independent;	//ADC工作模式:ADC1和ADC2工作在独立模式
    ADC_InitStructure1.ADC_ScanConvMode = ENABLE;	//模数转换工作在单通道模式
    ADC_InitStructure1.ADC_ContinuousConvMode = ENABLE;	//模数转换工作在单次转换模式
    ADC_InitStructure1.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;	//转换由软件而不是外部触发启动
    ADC_InitStructure1.ADC_DataAlign = ADC_DataAlign_Right;	//ADC数据右对齐
    ADC_InitStructure1.ADC_NbrOfChannel = 1;	//顺序进行规则转换的ADC通道的数目    
    ADC_Init(ADC3, &ADC_InitStructure1);	//根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器   
    
    
    
    ADC_RegularChannelConfig(ADC1,ADC_Channel_16,1,ADC_SampleTime_55Cycles5);
	ADC_RegularChannelConfig(ADC3,ADC_Channel_6,1,ADC_SampleTime_55Cycles5);
    
    DMA_Cmd(DMA1_Channel1,ENABLE);           								
	DMA_Cmd(DMA2_Channel5,ENABLE);           							
    ADC_Cmd(ADC1,ENABLE);	//使能指定的ADC1
    ADC_Cmd(ADC3,ENABLE);	//使能指定的ADC1
    
    ADC_DMACmd(ADC1,ENABLE);
    ADC_DMACmd(ADC3,ENABLE);
    
    ADC_ResetCalibration(ADC1);	//使能复位校准
    while(ADC_GetResetCalibrationStatus(ADC1));	//等待复位校准结束   
    ADC_StartCalibration(ADC1);	 //开启AD校准 
    while(ADC_GetCalibrationStatus(ADC1));	 //等待校准结束 
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);
    
    ADC_ResetCalibration(ADC3);	//使能复位校准  
    while(ADC_GetResetCalibrationStatus(ADC3));	//等待复位校准结束
    ADC_StartCalibration(ADC3);	 //开启AD校准
    while(ADC_GetCalibrationStatus(ADC3));	 //等待校准结束
    ADC_SoftwareStartConvCmd(ADC3, ENABLE);
}




short Get_Temprate(void)	//获取内部温度传感器温度值
{
	u32 adcx=0;
	short result=0;
 	double temperate=0;
	adcx=AD_Value1[0];	//读取通道16,20次取平均
    //USART1_printf(" temp:%d\r\n",adcx);
	temperate=(float)adcx*(3.3/4096);		//电压值 
	temperate=(1.43-temperate)/0.0043+25;	//转换为温度值 	 
	result=temperate*=100;					//扩大100倍.
	return result;
}

//读取Light Sens的值
//0~100:0,最暗;100,最亮 
u8 Lsens_Get_Val(void)
{
	u32 temp_val=0;
	temp_val=AD_Value2[0];//得到平均值 
    //USART1_printf(" light:%d\r\n",temp_val);
	if(temp_val>4000)temp_val=4000;
	return (u8)(100-(temp_val/40));
}

adc.h

#ifndef __ADC_H__
#define __ADC_H__
#include "sys.h"

extern uint16_t AD_Value1[1],AD_Value2[1];


void Adc_Init(void);
uint16_t Get_ADValue1(u8 ch);
uint16_t Get_ADValue2(u8 ch);
short Get_Temprate(void);
u8 Lsens_Get_Val(void);

#endif

2.串口部分

串口部分使用了串口1,使用串口接收的空闲中断,利用双缓存区的方法对DMA接收到的数据进行转运,防止数据产生覆盖和缓存空间的溢出。通过可变参串口打印函数,使其可以收发不定长数据,将printf只能用于单串口的局限性消除。

serial.c

#include "serial.h"

uint8_t USART1_TX_BUF[USART1_MAX_TX_LEN]; 	//发送缓冲,最大USART1_MAX_TX_LEN字节
uint8_t u1rxbuf[USART1_MAX_RX_LEN];			//发送数据缓冲区1
uint8_t u2rxbuf[USART1_MAX_RX_LEN];			//发送数据缓冲区2
uint8_t witchbuf=0;                  		//标记当前使用的是哪个缓冲区,0:使用u1rxbuf;1:使用u2rxbuf
uint8_t USART1_TX_FLAG;					//USART1发送标志,启动发送时置1
uint8_t USART1_RX_FLAG;					//USART1接收标志,启动接收时置1

void Serial_Init(u32 bound)
{
    USART_InitTypeDef USART_InitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
	//开启串口1和外设GPIO时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	//初始化串口的GPIO口
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;//发送TXD				
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 		 
	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;//接收RXD
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	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;//字长为8位数据格式
	USART_Init(USART1,&USART_InitStructure);
    
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 8;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);
	
	//DMA1通道5 NVIC 配置
	NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel5_IRQn;				//NVIC通道设置
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3 ;				//抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;						//子优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;							//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);											//根据指定的参数初始化NVIC寄存器
 
	//DMA1通道4 NVIC 配置
	NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;				//NVIC通道设置
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3 ;				//抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;						//子优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;							//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);											//根据指定的参数初始化NVIC寄存器
	
	USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);//开启串口接收中断
	USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);//开启串口空闲中断
	USART_ClearFlag(USART1,USART_FLAG_TC);//清除USART1标志位
    
	USART_Cmd(USART1,ENABLE);//使能串口1 	
}

void Serial_SendByte(uint8_t Byte)
{
	USART_SendData(USART1, Byte);
	while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}

void Serial_SendArray(uint8_t *Array, uint16_t Length)
{
	uint16_t i;
	for (i = 0; i < Length; i ++)
	{
		Serial_SendByte(Array[i]);
	}
}

void Serial_SendString(char *String)
{
	uint8_t i;
	for (i = 0; String[i] != '\0'; i ++)
	{
		Serial_SendByte(String[i]);
	}
}

uint32_t Serial_Pow(uint32_t X, uint32_t Y)
{
	uint32_t Result = 1;
	while (Y --)
	{
		Result *= X;
	}
	return Result;
}

void Serial_SendNumber(uint32_t Number, uint8_t Length)
{
	uint8_t i;
	for (i = 0; i < Length; i ++)
	{
		Serial_SendByte(Number / Serial_Pow(10, Length - i - 1) % 10 + '0');
	}
}

int fputc(int ch, FILE *f)
{
	Serial_SendByte(ch);
	return ch;
}


//可变参串口打印函数
void USART1_printf(char *format, ...)
{
	va_list arg_ptr;														//实例化可变长参数列表
	while(USART1_TX_FLAG);													//等待上一次发送完成(USART1_TX_FLAG为1即还在发送数据)
	va_start(arg_ptr, format); 												//初始化可变参数列表,设置format为可变长列表的起始点(第一个元素)
	// USART1_MAX_TX_LEN+1可接受的最大字符数(非字节数,UNICODE一个字符两个字节), 防止产生数组越界
	vsnprintf((char*)USART1_TX_BUF, USART1_MAX_TX_LEN+1, format, arg_ptr);	//从USART1_TX_BUF的首地址开始拼合,拼合format内容;USART1_MAX_TX_LEN+1限制长度,防止产生数组越界
	va_end(arg_ptr);														//注意必须关闭
	DMA_USART1_Tx_Data(USART1_TX_BUF,strlen((const char*)USART1_TX_BUF));	//发送USART1_TX_BUF内容
}


//串口通过DMA 发送数据
//buffer-->发送数据地址
//size-->发送的字节大小
void DMA_USART1_Tx_Data(u8 *buffer, u32 size)
{
	while(USART1_TX_FLAG);						//等待上一次发送完成(USART1_TX_FLAG为1即还在发送数据)
	USART1_TX_FLAG=1;							//USART1发送标志(启动发送)
	DMA1_Channel4->CMAR  = (uint32_t)buffer;	//设置要发送的数据地址
	DMA1_Channel4->CNDTR = size;    			//设置要发送的字节数目
	DMA_Cmd(DMA1_Channel4, ENABLE);				//开始DMA发送
}

//DMA1通道4中断,判断上次数据串口是否已经发送完成
void DMA1_Channel4_IRQHandler(void)
{
	if(DMA_GetITStatus(DMA1_IT_TC4)!= RESET)	//DMA接收完成标志
	{
		DMA_ClearITPendingBit(DMA1_IT_TC4); 	//清除中断标志 
		USART_ClearFlag(USART1,USART_FLAG_TC);	//清除串口1的标志位
		DMA_Cmd(DMA1_Channel4, DISABLE );   	//关闭USART1 TX DMA1 所指示的通道
		USART1_TX_FLAG=0;						//USART1发送标志(关闭)
	}
}

//串口1中断函数
void USART1_IRQHandler(void)                	
{
	uint8_t *p;
	uint8_t USART1_RX_LEN = 0;											//接收数据长度
	if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)			//串口1空闲中断
    {
            USART_ReceiveData(USART1); 									//清除串口1空闲中断IDLE标志位
            USART_ClearFlag(USART1,USART_FLAG_TC);						//清除USART1标志位
            DMA_Cmd(DMA1_Channel5, DISABLE );   						//关闭USART1 TX DMA1 所指示的通道
            USART1_RX_LEN = USART1_MAX_RX_LEN - DMA1_Channel5->CNDTR;	//获得接收到的字节数
            if(witchbuf)                        						//之前用的u1rxbuf,切换为u2rxbuf
            {
                p=u2rxbuf;												//先保存前一次数据地址再切换缓冲区
                DMA1_Channel5->CMAR=(u32)u1rxbuf;						//切换为u2rxbuf缓冲区地址
                witchbuf=0;                     						//下一次切换为u1rxbuf
            }
            else                               						//之前用的u1rxbuf,切换为u1rxbuf
            {
                p=u1rxbuf;												//先保存前一次数据地址再切换缓冲区
                DMA1_Channel5->CMAR=(u32)u2rxbuf;						//切换为u1rxbuf缓冲区地址
                witchbuf=1;                     						//下一次切换为u1rxbuf
            }
            DMA1_Channel5->CNDTR = USART1_MAX_RX_LEN;					//DMA通道的DMA缓存的大小
            DMA_Cmd(DMA1_Channel5, ENABLE);     						//使能USART1 TX DMA1 所指示的通道
            
            //******************数据处理******************//		
            DMA_USART1_Tx_Data(p,USART1_RX_LEN);
        
    }
}

serial.h

#ifndef __SERIAL_H
#define __SERIAL_H

#include "sys.h"
#include <stdio.h>
#include <stdarg.h>
#define USART1_MAX_TX_LEN 256
#define USART1_MAX_RX_LEN 256 
extern uint8_t USART1_TX_FLAG;					//USART1发送标志,启动发送时置1
extern uint8_t USART1_RX_FLAG;					//USART1接收标志,启动接收时置1	
extern size_t strlen(const char *);
extern uint8_t USART1_TX_BUF[USART1_MAX_TX_LEN]; 	//发送缓冲,最大USART1_MAX_TX_LEN字节
extern uint8_t u1rxbuf[USART1_MAX_RX_LEN];			//发送数据缓冲区1
extern uint8_t u2rxbuf[USART1_MAX_RX_LEN];			//发送数据缓冲区2
void Serial_Init(u32 bound);
void USART1_printf(char *format, ...);
void DMA_USART1_Tx_Data(u8 *buffer, u32 size);

void Serial_SendByte(uint8_t Byte);
void Serial_SendArray(uint8_t *Array, uint16_t Length);
void Serial_SendString(char *String);
uint32_t Serial_Pow(uint32_t X, uint32_t Y);
void Serial_SendNumber(uint32_t Number, uint8_t Length);
int fputc(int ch, FILE *f);

#endif

3.DMA配置

dma部分用到DMA1通道1、4、5分别作内部温度、串口发送、串口接收的数据转运;DMA2通道5用于光敏传感器数据转运,转运ADC是将数据从ADC的数据寄存器(ADCX->DR)转运到SRAM的数组AD_Value的数组中,转运串口是将接收的数据从串口的数据寄存器(USARTX->DR)转运到USARTX_TX_BUF的数据接收缓冲区中。

dma.c

#include "dma.h"
#include "adc.h"


void MyDMA_Init(void)
{
    
    DMA_InitTypeDef DMA_InitStructure;
    DMA_InitTypeDef DMA_InitStructure1;
    DMA_InitTypeDef DMA_InitStructure2;
    
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);
    
    DMA_DeInit(DMA1_Channel1);//内部温度传感器
    DMA_InitStructure1.DMA_MemoryBaseAddr=(uint32_t)AD_Value1;
	DMA_InitStructure1.DMA_MemoryDataSize=DMA_MemoryDataSize_HalfWord;
	DMA_InitStructure1.DMA_MemoryInc=DMA_MemoryInc_Disable;
	DMA_InitStructure1.DMA_PeripheralBaseAddr=(uint32_t)&ADC1->DR;
	DMA_InitStructure1.DMA_PeripheralDataSize=DMA_PeripheralDataSize_HalfWord;
	DMA_InitStructure1.DMA_PeripheralInc=DMA_PeripheralInc_Disable;
	DMA_InitStructure1.DMA_BufferSize=1;
	DMA_InitStructure1.DMA_DIR=DMA_DIR_PeripheralSRC;
	DMA_InitStructure1.DMA_M2M=DMA_M2M_Disable;
	DMA_InitStructure1.DMA_Mode=DMA_Mode_Circular;
    DMA_InitStructure1.DMA_Priority=DMA_Priority_High;
    DMA_Init(DMA1_Channel1,&DMA_InitStructure1); 
    
    DMA_DeInit(DMA2_Channel5);//PF8
    DMA_InitStructure2.DMA_MemoryBaseAddr=(uint32_t)AD_Value2;
	DMA_InitStructure2.DMA_MemoryDataSize=DMA_MemoryDataSize_HalfWord;
	DMA_InitStructure2.DMA_MemoryInc=DMA_MemoryInc_Disable;
	DMA_InitStructure2.DMA_PeripheralBaseAddr=(uint32_t)&ADC3->DR;
	DMA_InitStructure2.DMA_PeripheralDataSize=DMA_PeripheralDataSize_HalfWord;
	DMA_InitStructure2.DMA_PeripheralInc=DMA_PeripheralInc_Disable;
	DMA_InitStructure2.DMA_BufferSize=1;
	DMA_InitStructure2.DMA_DIR=DMA_DIR_PeripheralSRC;
	DMA_InitStructure2.DMA_M2M=DMA_M2M_Disable;
	DMA_InitStructure2.DMA_Mode=DMA_Mode_Circular;
    DMA_InitStructure2.DMA_Priority=DMA_Priority_High;
    DMA_Init(DMA2_Channel5,&DMA_InitStructure2); 
    
	DMA_DeInit(DMA1_Channel4);  //tx  发送数据
    DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART1->DR);   
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)USART1_TX_BUF;    
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;   
    DMA_InitStructure.DMA_BufferSize = USART1_MAX_TX_LEN;  
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;    
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;  
	DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;  
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;  
    DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;  
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  
    DMA_InitStructure.DMA_Priority=DMA_Priority_Medium;
    DMA_Init(DMA1_Channel4,&DMA_InitStructure);  
	
	DMA_DeInit(DMA1_Channel5);  
    DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART1->DR);   
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)u1rxbuf;   
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;  
    DMA_InitStructure.DMA_BufferSize = USART1_MAX_RX_LEN;  
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;  
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;  
    DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;  
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;  
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;  
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    DMA_InitStructure.DMA_Priority=DMA_Priority_Medium;    
    DMA_Init(DMA1_Channel5,&DMA_InitStructure); 
	
    DMA_ITConfig(DMA1_Channel5,DMA_IT_TC,ENABLE);							//开USART2 Rx DMA中断
	DMA_ITConfig(DMA1_Channel4,DMA_IT_TC,ENABLE);							//开USART2 Tx DMA中断
	DMA_ITConfig(DMA1_Channel1,DMA_IT_TC,ENABLE);							//开USART2 Rx DMA中断
	DMA_ITConfig(DMA2_Channel5,DMA_IT_TC,ENABLE);							//开USART2 Tx DMA中断
    
    DMA_Cmd(DMA1_Channel5,ENABLE);           								//使DMA通道5停止工作
	DMA_Cmd(DMA1_Channel4,DISABLE);           								//使DMA通道4停止工作

    
	USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);        					//开启串口DMA发送
	USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);        					//开启串口DMA接收
    
}


dma.h

#ifndef __DMA_H
#define __DMA_H

#include "sys.h"
#include "serial.h"

    
void MyDMA_Init(void);


#endif

4.main函数

main.c

#include "delay.h"
#include "lcd.h"
#include "dma.h"
#include "serial.h"
#include "adc.h"


int main(void)
{	
    short temp=0;
    u8 adcx;
	delay_init();
    Serial_Init(115200);
	MyDMA_Init();
    LCD_Init();
    Adc_Init();
    POINT_COLOR=RED;//设置字体为红色 
    LCD_ShowString(30,140,200,16,16,"TEMPERATE: 00.00C");
    LCD_ShowString(30,156,200,16,16,"LSENS_VAL:");	
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);
    ADC_SoftwareStartConvCmd(ADC3, ENABLE);
	while(1)
	{
        temp=Get_Temprate();	//得到温度值 
		if(temp<0)
		{
			temp=-temp;
			LCD_ShowString(30+10*8,140,16,16,16,"-");	//显示负号
		}else LCD_ShowString(30+10*8,140,16,16,16," ");	//无符号		
		LCD_ShowxNum(30+11*8,140,temp/100,2,16,0);		//显示整数部分
		LCD_ShowxNum(30+14*8,140,temp%100,2,16, 0X80);	//显示小数部分
        
        USART1_printf(" TEMPERATE:%d.%d\r\n",temp/100,temp%100);
        adcx=Lsens_Get_Val();
        LCD_ShowxNum(30+10*8,156,adcx,3,16,0);//显示ADC的值 
        USART1_printf(" LSENS_VAL:%d\r\n",adcx);
        
        delay_ms(250);
	}
}


总结

以上就是今天要讲的内容,本文是笔者在stm32学习中将adc采集和串口外设接收的数据通过DMA进行转运,进一步理解DMA的配置和转运数据的机制,加深对个外设的理解

  • 5
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值