IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 基于STM32F407 ADC双通道 PS2游戏机摇杆ADC采集 -> 正文阅读

[嵌入式]基于STM32F407 ADC双通道 PS2游戏机摇杆ADC采集

一、PS2游戏机摇杆概述

1.1PS2游戏机摇杆概述

摇杆一般在航模中的无人机、电玩、遥控车、云台等设备上应用广泛,很多带有屏幕的设备也经常使用摇杆作为菜单选择的输入控制。

PS2游戏双轴摇杆传感器模块由采用原装优质金属PS2摇杆电位器制作,具有2轴(X,Y)模拟输出,1路(Z)按钮数字输出。

原理:摇杆为一个双向十字的10K电阻器。模块使用5V供电,原始状态下X、Y读出电压约为2.5V,当摇杆往某个方向推动,输出的相应轴电压值增加或减小,大值5V,小值0V。

1、工作电压:5V
2、输出电压范围:0~5V
3、接口:两路模拟信号代表X、Y偏移量,一路数字信号SW代表Z轴是否按下

在这里插入图片描述

1.2PS2游戏机摇杆图解

在这里插入图片描述
(1)SW:标识符为摇杆按下时触发,引脚电平为高低电平变化,但是我通过万用表进行测量时,没有电平变化,且引脚电平是不通过的,不知道是不是买的这个模块有问题,在编程过程中其实也不难,加个中断即可。(2)VRY:输出Y轴电压变化范围:0~3.3V 或 0~5V ;电压范围取决于+5V标识的连接方式
(3)VRX:输出Y轴电压变化范围:0~3.3V 或 0~5V;电压范围取决于+5V标识的连接方式
(4)GND:接电源地即可
(5)+5V:这个是接电压的,虽然写着+5V,但是也可以接3.3V(如果接3.3V, X轴与Y轴的电压变化范围:0~3.3V),由于STM32F407 ADC的参考电压为3.3V,所以此引脚接3.3V

X、Y转电压增量变化如图

在这里插入图片描述

二、硬件连接分析

由于X、Y轴输出的是电压可变的量,且有两个ADC需要同时进行采集,故将采用ADC的双通道进行设计,通过查找手册,确定使用ADC1 通道2及通道3
在这里插入图片描述
由于需要进行快速的响应采集速度,故使用DMA的方式进行转换的方式,通过查找手册知道ADC1与DMA的关系为

在这里插入图片描述

三、代码实现

3.1 ADC代码

adc.c

#include "adc.h"

//用于存储PA2 PA3的ADC值
__IO uint16_t aADCDualConvertedValue[2];



/*************************************
硬件说明
PA2 -- ADC123_IN2
PA3 -- ADC123_IN3


选用ADC1

*************************************/

void ADC_PA2_PA3_Init(void)
{

	GPIO_InitTypeDef  		GPIO_InitStructure;
	ADC_CommonInitTypeDef 	ADC_CommonInitStructure;
	ADC_InitTypeDef       	ADC_InitStructure;

	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能GPIOA时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //使能ADC1时钟	
	
	
	GPIO_InitStructure.GPIO_Pin 	= GPIO_Pin_2|GPIO_Pin_3; 	//引脚2 3
	GPIO_InitStructure.GPIO_Mode 	= GPIO_Mode_AN;				//模拟模式
	GPIO_InitStructure.GPIO_PuPd 	= GPIO_PuPd_NOPULL ;		//浮空
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	复位ADC寄存器
	RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1,ENABLE);	  	//reset adc
	RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1,DISABLE);	//end reset adc


	ADC_CommonInitStructure.ADC_Mode 				= ADC_Mode_Independent;				//独立模式
	ADC_CommonInitStructure.ADC_TwoSamplingDelay 	= ADC_TwoSamplingDelay_20Cycles;
	ADC_CommonInitStructure.ADC_DMAAccessMode 		= ADC_DMAAccessMode_Disabled; 		//这是混合ADC才使用的模式,这里由于是独立模式,选择参数ADC_DMAAccessMode_Disabled
	ADC_CommonInitStructure.ADC_Prescaler 			= ADC_Prescaler_Div4;//预分频4分频。ADCCLK=PCLK2/4=84/4=21Mhz,ADC时钟最好不要超过36Mhz 
	ADC_CommonInit(&ADC_CommonInitStructure);//初始化

	ADC_InitStructure.ADC_Resolution 			= ADC_Resolution_12b;	//12位模式
	ADC_InitStructure.ADC_ScanConvMode 			= ENABLE;				//扫描模式	多通道采集需要
	ADC_InitStructure.ADC_ContinuousConvMode 	= ENABLE;				//连续转换
	ADC_InitStructure.ADC_ExternalTrigConvEdge 	= ADC_ExternalTrigConvEdge_None;//禁止触发检测,使用软件触发
//	ADC_InitStructure.ADC_ExternalTrigConv		= ADC_ExternalTrigConv_T3_CC1;	//禁止硬件触发,些值可以不用填写
	ADC_InitStructure.ADC_DataAlign 			= ADC_DataAlign_Right;//右对齐	
	ADC_InitStructure.ADC_NbrOfConversion 		= 2;//2个转换在规则序列中

	ADC_Init(ADC1, &ADC_InitStructure);//ADC初始化

	// 配置 ADC 通道转换顺序和采样时间周期
	ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 1, ADC_SampleTime_15Cycles );	//ADC1,ADC通道,480个周期,提高采样时间可以提高精确度		
	ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 2, ADC_SampleTime_28Cycles );	//ADC1,ADC通道,480个周期,提高采样时间可以提高精确度			    
	 

	// 使能 DMA 请求 after last transfer (Single-ADC mode)
	ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);

	//使能 ADC DMA
	ADC_DMACmd(ADC1, ENABLE);

	//ADC_ExternalTrigConvCmd(ADC1, ENABLE); 
	ADC_Cmd(ADC1, ENABLE);//开启AD转换器	

}



void DMA_Config(void)
{
	DMA_InitTypeDef DMA_InitStructure;

	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);

	DMA_InitStructure.DMA_Channel 				= DMA_Channel_0;				//选择 DMA 通道,通道存在于流中0中
	DMA_InitStructure.DMA_PeripheralBaseAddr 	= (uint32_t)&(ADC1->DR);		//数据源在ADC1->DR中
	DMA_InitStructure.DMA_Memory0BaseAddr 		= (uint32_t)aADCDualConvertedValue;//数据目的地在aADCDualConvertedValue数组
	DMA_InitStructure.DMA_DIR 					= DMA_DIR_PeripheralToMemory;//数据传输方向为外设到存储器
	DMA_InitStructure.DMA_BufferSize 			= 2;    						//与通道数设置一致
	DMA_InitStructure.DMA_PeripheralInc 		= DMA_PeripheralInc_Disable;	// 外设寄存器只有一个,地址不用递增
	DMA_InitStructure.DMA_MemoryInc 			= DMA_MemoryInc_Enable;			// 存储器地址固定
	DMA_InitStructure.DMA_PeripheralDataSize 	= DMA_PeripheralDataSize_HalfWord;	// 外设数据大小为半字,即两个字节
	DMA_InitStructure.DMA_MemoryDataSize	 	= DMA_PeripheralDataSize_HalfWord;	// 存储器数据大小也为半字,跟外设数据大小相同
	DMA_InitStructure.DMA_Mode 					= DMA_Mode_Circular;				// 循环传输模式
	DMA_InitStructure.DMA_Priority 				= DMA_Priority_High;				// DMA 传输通道优先级为高,当使用一个 DMA 通道时,优先级设置不影响
	DMA_InitStructure.DMA_FIFOMode 				= DMA_FIFOMode_Disable;            // 禁止 DMA FIFO ,使用直连模式
	// FIFO 大小, FIFO 模式禁止时,这个不用配置
	DMA_InitStructure.DMA_FIFOThreshold 		= DMA_FIFOThreshold_HalfFull;
	DMA_InitStructure.DMA_MemoryBurst 			= DMA_MemoryBurst_Single;
	DMA_InitStructure.DMA_PeripheralBurst 		= DMA_PeripheralBurst_Single;
	DMA_Init(DMA2_Stream0, &DMA_InitStructure);
	
	//使能 DMA 流
	DMA_Cmd(DMA2_Stream0, ENABLE);
	
}

adc.h

#ifndef __ADC_H
#define __ADC_H


#include "stm32f4xx.h"


void ADC_PA2_PA3_Init(void);
void DMA_Config(void);

#endif

3.1 定时器

在这里,我选择每隔1S采集ADC的值,如果在项目中需要快速采集,则减少定时器中断即可
tim.c

#include "tim.h"

/*********************************************
功能说明:
TIM3 -- APB1 -- 16位定时器(65535)
TIM3时钟频率: APB1*2 = 42*2 = 84MHZ
**********************************************/

void Tim3_Init(void)
{
	NVIC_InitTypeDef  NVIC_InitStruct;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseInitStruct;
	
	//	1、使能定时器时钟。
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	
	

	TIM_TimeBaseInitStruct.TIM_Prescaler		= 8400-1;   			//8400分频  84000 000HZ/84000 = 10000HZ
	TIM_TimeBaseInitStruct.TIM_Period			= 10000-1;   			//计10000个数,用时1s
	TIM_TimeBaseInitStruct.TIM_CounterMode		= TIM_CounterMode_Up; 	//向上计数
	TIM_TimeBaseInitStruct.TIM_ClockDivision	= TIM_CKD_DIV1;			//分频因子
	//	2、初始化定时器,配置ARR,PSC。
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStruct);	
	
	NVIC_InitStruct.NVIC_IRQChannel						= TIM3_IRQn;		//中断通道 ,在stm32f4xx.h
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority	= 2;				//抢占优先级
 	NVIC_InitStruct.NVIC_IRQChannelSubPriority			= 2;				//响应优先级
	NVIC_InitStruct.NVIC_IRQChannelCmd					= ENABLE;			//中断通道使能 
	//	3、启定时器中断,配置NVIC。
    NVIC_Init(&NVIC_InitStruct);
	
	//	4、设置 TIM3_DIER  允许更新中断
	TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
	//	5、使能定时器。
	TIM_Cmd(TIM3, ENABLE);
	
}

tim.h

#ifndef __TIM_H
#define __TIM_H

#include "stm32f4xx.h"

void Tim3_Init(void);


#endif

3.2 主函数

#include "stm32f4xx.h"
#include "adc.h"
#include "delay.h"
#include "usart.h"
#include "tim.h"


//用于存储PA2 PA3的ADC值
extern __IO uint16_t aADCDualConvertedValue[2];
unsigned int adcVal,adcVal01,adcVal02;
char msgstr[64];

int main(void)
{
	//设置系统中断优先级分组2
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	Delay_Init();
	Usart1_Init(115200);
	ADC_PA2_PA3_Init();
	DMA_Config();	

	//1S产生一次中断,在中断获取ADC数据
	Tim3_Init();
	//开始 adc 转换,软件触发
	ADC_SoftwareStartConv(ADC1);
	while(1)
	{
		delay_s(1);//延时200ms

	};
	
	return 0;
}


//	6、编写中断服务函数。
void TIM3_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM3, TIM_IT_Update) == SET)
	{
		printf("While Run...\r\n");
	
		adcVal01= aADCDualConvertedValue[0];			
		adcVal02= aADCDualConvertedValue[1];	
		printf("X轴电压:%f, Y轴电压:%f\r\n", (adcVal01/4095.0)*3.3 , (adcVal02/4095.0)*3.3);
		sprintf(msgstr,"PA2 ch2=%d PA3 ch3=%d\r\n",adcVal01,adcVal02);		
		printf(msgstr);		  
		
		printf("\r\n");
	
	}
	//清除中断线0标志位
    TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
}

四、实验效果分析

将程序下载到开发板后,打开串口,通过摇杆,即可改变不同的电压
在这里插入图片描述
单个的PS游戏摇杆就写到这里了。两个摇杆的话,写成四通道即可。源码链接:https://download.csdn.net/download/wwwqqq2014/85309506?spm=1001.2014.3001.5503

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-05-09 12:53:52  更:2022-05-09 12:54:05 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 2:54:05-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码