STM32F103:使用DMA和ADC读取游戏摇杆模块
创作时间:
2025-01-22 00:16:42
作者:
@小白创作中心
STM32F103:使用DMA和ADC读取游戏摇杆模块
游戏摇杆模块简介
游戏摇杆模块可以通过网购轻松获得,价格大约在1到2元人民币。模块上有5个引脚,从上到下依次为GND、+5V、URX、URY和SW。虽然模块上标注的是5V,但实测表明,STM32F103C8T6的3.3V供电也能正常使用。URX和URY分别输出X轴和Y轴的信号量,SW则连接到摇杆侧面的按钮,当摇杆被按下时,按钮会被触发。
技术方案
摇杆模块的三个信号量(XYZ三轴)需要不同的处理方式。XY轴的信号可以通过ADC进行数值获取,而Z轴作为一个按键信号,适合使用GPIO口的外部中断来检测。考虑到XY轴有两个通道,可以配置ADC与DMA联动,配合ADC的循环转换和扫描转换功能,实现自动数据采集。
DMA技术详解
DMA(Direct Memory Access)即直接存储器访问,能够在不依赖CPU的情况下,快速完成数据搬运任务。STM32F103C8T6属于中容量产品,只包含一个DMA控制器(DMA1),共有7个通道。每个通道对应不同的外设,需要根据具体应用查询映射关系。
使用DMA主要分为三步:
- 打开时钟
- 配置初始化
- 上电使能
DMA配置函数
- RCC_AHBPeriphClockCmd:用于打开DMA时钟
- DMA_Init:配置DMA通道参数
- DMA_BufferSize:设置DMA缓存大小
- DMA_DIR:设置数据传输方向
- DMA_M2M:设置是否为存储器到存储器的传输
- DMA_MemoryBaseAddr:设置存储器基地址
- DMA_MemoryDataSize:设置存储器数据大小
- DMA_PeripheralInc:设置外设地址是否自增
- DMA_Priority:设置优先级
- DMA_MemoryInc:设置存储器地址是否自增
- DMA_Mode:设置DMA传输模式
- DMA_PeripheralBaseAddr:设置外设基地址
- DMA_PeripheralDataSize:设置外设数据大小
- DMA_Cmd:使能DMA通道
实验现象
- 静止状态:
- 向左扳动时:
- 按下状态时:
代码实现
#include "stm32f10x.h"
#include "Delay.h"
#include "OLED.h"
uint16_t xy[2];
void interruptInit(void){
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef gitd;
gitd.GPIO_Mode=GPIO_Mode_IPU;
gitd.GPIO_Pin=GPIO_Pin_6;
gitd.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&gitd);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource6);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef nitd;
nitd.NVIC_IRQChannel=EXTI9_5_IRQn;
nitd.NVIC_IRQChannelCmd=ENABLE;
nitd.NVIC_IRQChannelPreemptionPriority=2;
nitd.NVIC_IRQChannelSubPriority=2;
NVIC_Init(&nitd);
EXTI_InitTypeDef eitd;
eitd.EXTI_Line=EXTI_Line6;
eitd.EXTI_LineCmd=ENABLE;
eitd.EXTI_Mode=EXTI_Mode_Interrupt;
eitd.EXTI_Trigger=EXTI_Trigger_Falling;
EXTI_Init(&eitd);
}
int main(void){
OLED_Init();
interruptInit();
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
RCC_ADCCLKConfig(RCC_PCLK2_Div6);
GPIO_InitTypeDef gitd;
gitd.GPIO_Mode=GPIO_Mode_AIN;
gitd.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1;
gitd.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&gitd);
ADC_InitTypeDef itd;
itd.ADC_ContinuousConvMode=ENABLE;
itd.ADC_DataAlign=ADC_DataAlign_Right;
itd.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;
itd.ADC_Mode=ADC_Mode_Independent;
itd.ADC_NbrOfChannel=2;
itd.ADC_ScanConvMode=ENABLE;
ADC_Init(ADC1,&itd);
ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_55Cycles5);
ADC_RegularChannelConfig(ADC1,ADC_Channel_1,2,ADC_SampleTime_55Cycles5);
DMA_InitTypeDef ditd;
ditd.DMA_BufferSize=2;
ditd.DMA_DIR=DMA_DIR_PeripheralSRC;
ditd.DMA_M2M=DMA_M2M_Disable;
ditd.DMA_MemoryBaseAddr=(uint32_t)&xy;
ditd.DMA_MemoryDataSize=DMA_MemoryDataSize_HalfWord;
ditd.DMA_MemoryInc=DMA_MemoryInc_Enable;
ditd.DMA_Mode=DMA_Mode_Circular;
ditd.DMA_PeripheralBaseAddr=(uint32_t)&ADC1->DR;
ditd.DMA_PeripheralDataSize=DMA_PeripheralDataSize_HalfWord;
ditd.DMA_PeripheralInc=DMA_PeripheralInc_Disable;
ditd.DMA_Priority=DMA_Priority_Medium;
DMA_Init(DMA1_Channel1,&ditd);
DMA_Cmd(DMA1_Channel1,ENABLE);
ADC_DMACmd(ADC1,ENABLE);
ADC_Cmd(ADC1,ENABLE);
ADC_ResetCalibration(ADC1);
while(SET==ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(SET==ADC_GetCalibrationStatus(ADC1));
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
OLED_ShowString(1,1,"X:");
OLED_ShowString(2,1,"Y:");
while(1){
int x=0,y=0;
for(uint8_t i=0;i<10;++i) x+=xy[0];
for(uint8_t i=0;i<10;++i) y+=xy[1];
x/=10;y/=10;
OLED_ShowNum(1,3,x,5);
OLED_ShowNum(2,3,y,5);
}
}
void EXTI9_5_IRQHandler(void){
if(EXTI_GetITStatus(EXTI_Line6)){
if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_6)==0){
OLED_ShowString(3,1,"Z DOWN");
Delay_ms(20);
while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_6)==0);
Delay_ms(20);
OLED_ShowString(3,1," ");
}
EXTI_ClearITPendingBit(EXTI_Line6);
}
}
参考资料
- 《STM32F10xxx参考手册(中文)》
- 《ARM Cortex-M3 嵌入式原理及应用 基于STM32F103微控制器》
- 《STM32F103xx固件函数库用户手册》
热门推荐
流感高峰来袭,小心感冒后嗅觉失踪!
感冒后嗅觉失灵?这些方法帮你找回“香气四溢”的世界!
猫咪疯狂舔毛的背后真相:是皮肤病还是心理问题?
为什么狗喜欢啃骨头
蓝猫掉毛怎么办?这些方法帮你解决烦恼!
健康为前提,猫咪必喂的东西有哪些
猫咪为什么要吃自己的毛(探究猫咪吃毛背后的原因与危害)
怎样预防肝病和治疗肝炎
王羲之与“天下第一行书”:《兰亭序》的前世今生
泰山黄精茶:简单三步制作,多重功效助力养生
山药红枣大米粥:营养搭配与制作全攻略
宁波东站到机场:公交换乘机场大巴或打车,两种方式详解
黔南茶乡、六盘水雪场:贵州两条线路入选全国乡村旅游精品
单霁翔推出故宫系列新作,详解紫禁城建筑、文物与人物
重庆旅游:自由行还是跟团游?这份攻略帮你轻松决定
“中原小白”诞生记:首只中原帝企鹅宝宝的奇妙成长之旅
帝企鹅的极地生存智慧:从生理到行为的多重适应
帝企鹅的极寒生存法则,竟然这么酷?
从外在到内在:十大方法塑造既专业又优雅的完美形象
希拉穆仁草原:内蒙古的自然瑰宝与文化明珠
希拉穆仁草原:四季美景不容错过
希拉穆仁草原必打卡特色项目:热气球系留飞
上市公司股票回购潮:优化资本结构还是粉饰业绩?
科创板10月现回购潮:89家公司参与,金额超6亿
深圳北站周边十大景点全攻略:从文化到自然,从购物到娱乐
算命中刑伤是什么命
糯米食品的营养价值与食用建议
耳朵突然闷堵、耳鸣,小心突发性耳聋
耳朵闷闷的缓解方法
癌症免疫疗法:突破传统治疗局限,开启精准医疗新篇