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

news/2024/10/18 12:31:23/

目录

前言

一、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最大时间不能超过14MGPIO_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);	//使能指定的ADC1ADC_Cmd(ADC3,ENABLE);	//使能指定的ADC1ADC_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接收标志,启动接收时置1void 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;//接收RXDGPIO_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);//PF8DMA_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的配置和转运数据的机制,加深对个外设的理解


http://www.ppmy.cn/news/733526.html

相关文章

RGB环形补光灯行业头部企业市场占有率及排名调研报告

本文调研和分析全球RGB环形补光灯发展现状及未来趋势&#xff0c;核心内容如下&#xff1a; &#xff08;1&#xff09;全球市场总体规模&#xff0c;分别按销量和按收入进行了统计分析&#xff0c;历史数据2018-2022年&#xff0c;预测数据2023至2029年。 &#xff08;2&#…

【51单片机学习】(1):单片机入门

1.C51数据类型 在C51中int只占两个字节 2.RAM和ROM ROM&#xff1a;(Read Only Memory) 程序存储器在单片机中用来存储程序数据及常量数据或变量数据&#xff0c;凡是c文件及h文件中所有代码、全局变量、局部变量、const’限定符定义的常量数据、startup.asm文件中的代码(类…

【32单片机学习】(1)stm32位带操作

位带区操作 STM32F10x支持位带操作的两个内存区的范围是&#xff1a; 0x2000_0000-0x200F_FFFF&#xff08;SRAM 区中的最低 1MB&#xff09; 0x4000_0000-0x400F_FFFF&#xff08;片上外设区中的最低 1MB&#xff09; 例如操作GPIOB5->ODR寄存器&#xff08;GPIOB_ODR寄…

【32单片机学习】(2)stm32库文件

startup_stm32f10x_hd.s 设置堆栈指针、设置PC指针、初始化中断向量表、配置系统时钟、调用C库函数_main&#xff0c;将汇编环境转到C语言编译环境 ; Reset handler //程序从此处开始 Reset_Handler PROCEXPORT Reset_Handler [WEAK]IMPORT __mainIMPORT S…

【51单片机学习】(2)定时器扫描实现按键长按和短按

用Delay消抖时会导致主程序中的一些进程受到影响&#xff0c;所以在这里借鉴江科大使用定时器扫描按键状态进行消抖的方法。在实际使用中加入了长按功能 按键驱动代码key.c #include <REGX52.H>unsigned char Key_KeyNumber,KeyTime,KeyCount,i; unsigned int times;/**…

【32单片机学习】(7)STM32时钟周期

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 1.理论时间 2.官方设计标准时间 3.时钟周期的应用 前言 在学习stm32的I2C部分时&#xff0c;发现和C51的有所不同&#xff0c;stm32在SCL翻转IO口后要一定的等…

【32单片机学习】(6)STM32串口+DMA收发不定长数据

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 1.DMA介绍 2.串口接收数据 3.实验现象 1.实验电路图 2.串口收发不定长数据视频演示 3.OLED 显示接收数据 4.代码部分 1.1串口模块 serial.c serial.h …

【32单片机学习】(8)STM32滴答定时器

1.选择时钟源 在misc.c文件中&#xff0c;配置SysTick时钟源 void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource); 可以选择系统时钟或者系统时钟的8分频&#xff1a; arg SysTick_CLKSource_HCLK_Div8: AHB clock divided by 8 selected as SysTick clock source.…