您现在的位置是:POS机营销网 > 电签POS机

pos机f1按键作用,STM32F103C8T6制作舵机测试仪详细图文教程

POS机营销网2025-04-25 12:05:06【电签POS机】9人已围观

简介网上有很多关于pos机f1按键作用,STM32F103C8T6制作舵机测试仪详细图文教程的知识,也有很多人为大家解答关于pos机f1按键作用的问题,今天乐刷官方代理商(b06.cn)为

【温馨提示】如果您有办理pos机的需求或者疑问,可以联系官方微信 18127011016

POS机办理

网上有很多关于pos机f1按键作用,STM32F103C8T6制作舵机测试仪详细图文教程的机键作机测教程知识,也有很多人为大家解答关于pos机f1按键作用的制作舵问题,今天乐刷官方代理商(www.zypos.cn)为大家整理了关于这方面的试仪知识,让我们一起来看下吧!

本文目录一览:

1、详细pos机f1按键作用

pos机f1按键作用,STM32F103C8T6制作舵机测试仪详细图文教程

pos机f1按键作用

自主学习stm32已有一周,图文先实现一个小demo,机键作机测教程算是制作舵给自己一个动力叭,有目标的试仪学习收获会更多。虽然本科也修了嵌入式课程,详细但那种走马观花式的图文学习,最后真正得到的机键作机测教程知识实在寥寥无几。个人理解,制作舵学习STM32不只是试仪学习编程,更多的详细是学习查资料、查数据手册、图文软件的使用和调试方法上,真正需要自己从头造的部分不是很多,吸取前人的经验,搬过来取自己所需即可。用农夫山泉的话来说就是,我们不生产代码,我们只是代码的搬运工!

pos机f1按键作用,STM32F103C8T6制作舵机测试仪详细图文教程

这次主要跟着正点原子的开发资料进行学习,没有使用战舰开发板,而是使用STM32F103C8T6板子。一是避免自己直接把例程的代码烧进开发板,最后啥也没学到,在不同的板子间移植代码过程中,能够掌握理解更多的基础知识和调试经验;二是这个小板子廉价易得,只要十块钱,和大几百的开发板相比,它体积小、资源可观,很适合我的小项目,以后准备用来制作航模遥控器,敬请关注哈~

1.材料清单

1.STM32F103C8T6蓝色开发板*1(黑色板也可以)

2.USB转TTL模块*1

3. ST-LINK V2仿真器下载器*1(调试STM32性价比极高)

4. OLED屏幕(4管脚)*1

5.10k电位器*1(10k以上都可)

6. 杜邦线、面包板、导线、插针若干

2.电路连接

电位器:GND - PA0 - 3.3VOLED显示屏:GND 电源地VCC 接3.3v电源SCL 接PB8(SCL)SDA 接PB9(SDA)

ST-LINK V2接法:GND 电源地3V3 接3.3vSWCLK 接DCLKSWDIO 接DIO串口USB-TTL接法:GND 电源地3V3 接3.3vTXD 接PB7RXD 接PB6PWM输出:PB5

实物连接图如下:

3.安装keil5

安装及破解MDK(Keil5)教程 https://blog.csdn.net/weixin_42911200/article/details/81590158

注意要安装keil.STM32F1xx_DFP.2.3.0.pack支持包,因为我们要用STM32F103C8T6芯片的库函数编写。

库下载地址:https://www.keil.com/dd2/Pack/

博主已上传天翼云盘:https://cloud.189.cn/t/vyUBFzyuMBZr(访问码:6sng)

等待网页加载完,在列表里找到Keil,再找STMicroelectronics STM32F1 Series Device Support, Drivers and

4.新建工程

新建keil库函数工程 https://www.cnblogs.com/zeng-1995/p/11308622.html

与链接里面不同的是以下几个设置:

点击图标按钮1,打开Manage Run-Time Environment窗口,Device如下勾选,其他栏与链接中相同;

点击图标按钮2,打开Manage Project Items窗口,Groups和 Files如下设置:

点击图标按钮3,打开Options for Target窗口,点击顶部菜单按钮切换子窗口,依次如下设置:

点击Setting,打开Cortex-M Target Driver Setup窗口,如果SWDIO里面未显示序列号,则电脑需要更新ST-LINK驱动。

解决方法见链接 https://blog.csdn.net/qq_42041980/article/details/92015997

5.程序实现

控制舵机的PWM:周期20ms,高电平时间0.5ms~2.5ms变化,可控制舵机0~180°的角度变化,即每个高电平时间都对应舵机的一个角度。但航模舵面的实际控制中,不可能有180°变化,所以通用的高电平宽度其实是1ms~2ms。

具体可参考https://www.moz8.com/forum.php?mod=viewthread&tid=82875&highlight=舵机测试仪

控制无刷电调所用的PWM信号高电平时间也是1ms~2ms,所以我们要实现的PWM信号周期20ms,高电平时间1ms~2ms。

我们使用ADC1读取电位器的电压采样值,并从0~4095范围的采样值转换到1000~2000,赋值给PWM输出。TIM2定时触发ADC采样,通过DMA传输给变量所在的寄存器,取10次进行均值滤波,消除抖动。

定时器触发ADC,DMA传输 http://www.openedv.com/forum.php?mod=viewthread&tid=277863&extra=&page=1

定时器TIM触发ADC采样,DMA搬运到内存 https://blog.csdn.net/qq_38410730/article/details/89921413

TIM3定时触发产生PWM信号,预分频72,频率1MHz,周期1us;自动装载值20 000,故PWM周期1us*20 000=20ms。

主要代码如下:

main.c文件-包含程序说明、主函数

/*=============舵机测试仪==============芯片STM32F103C8T6,使用ADC读取电位器的电压采样值,0~4095转换到1000~2000,赋值给PWM输出。 TIM2定时触发ADC采样,通过DMA传输给变量ch1Value,取10次进行均值滤波。控制舵机的PWM:周期20ms,高电平时间0.5ms~2.5ms变化,可控制舵机0~180°的角度变化, 但航模舵面的实际控制中,不可能有180°变化,所以通用的高电平宽度其实是1ms~2ms电位器:GND - PA0 - 3.3VOLED显示屏:GND 电源地VCC 接3.3v电源SCL 接PB8(SCL)SDA 接PB9(SDA)串口USB-TTL接法:GND 电源地3V3 接3.3vTXD 接PB7RXD 接PB6ST-LINK V2接法:GND 电源地3V3 接3.3vSWCLK 接DCLKSWDIO 接DIOPWM输出:PB5by Bilibili 蔡子CaiZi*/#include "config.h"#include "delay.h"#include "usart.h"#include "stm32f10x.h"#include "oled.h"#include "RTC.h" #include "stdio.h"#include "string.h" int main(){u8 txt[16]=;delay_init();//初始化延时函数NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2,2位抢占优先级和2位子优先级usart_init(115200);//初始化串口1,波特率为115200TIM3_PWM_Init(19999,71);//预分频72,频率1MHz,周期1us;自动装载值20 000,故PWM周期1us*20 000TIM2_Init(499,71);//1MHz,每500us采集一次;可设置9us以上,但过小影响OLED显示DMA1_Init();//DMA初始化GPIOA_Init();//PA初始化Adc_Init();//ADC初始化RTC_Init(); //RTC初始化OLED_Init();//初始化OLED OLED_Clear(); while (1){itoa(PWM1value,txt,10);//将int类型转换成10进制字符串//printf("采样值:%d舵量:%s",ch1Value,txt);//printf("当前时间:%d:%d:%d",calendar.hour,calendar.min,calendar.sec);//OLED_Clear();//一直清屏会造成闪烁strcat(txt," us");//合并字符串OLED_ShowString(6,3,txt,24); //位置6,3;字符大小24*24点阵OLED_Refresh_Gram();delay_ms(1);}}

config.c文件-包含TIM/ GPIO/ ADC等初始化函数

#include "config.h"#include "delay.h"#include "usart.h"#include "sys.h"#include "rtc.h" volatile u16 ch1Value[10];//ADC采样值volatile u16 PWM1value;//控制PWM占空比#define ADC1_DR_Address ((u32)0x4001244C)//ADC1的地址//通用定时器2中断初始化//这里时钟选择为APB1的2倍,而APB1为36M//arr:自动重装值。//psc:时钟预分频数//这里使用的是定时器2控制ADC定时采样void TIM2_Init(u16 arr,u16 psc){TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_OCInitTypeDef TIM_OCInitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //时钟使能 //定时器TIM2初始化TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_timTIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);//根据指定的参数初始化TIMx的时间基数单位TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//选择定时器模式:TIM脉冲宽度调制模式1TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//比较输出使能TIM_OCInitStructure.TIM_Pulse = 9;//计数达到9产生中断TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;//输出极性:TIM输出比较极性低TIM_OC2Init(TIM2, & TIM_OCInitStructure);//初始化外设TIM2_CH2TIM_Cmd(TIM2, ENABLE); //使能TIMxTIM_CtrlPWMOutputs(TIM2, ENABLE);} //DMA1配置void DMA1_Init(void){DMA_InitTypeDef DMA_InitStructure;NVIC_InitTypeDef NVIC_InitStructure; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE); //使能ADC1通道时钟//DMA1初始化DMA_DeInit(DMA1_Channel1);DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;//ADC1地址DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ch1Value; //ch1Value的内存地址DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //方向(从外设到内存)DMA_InitStructure.DMA_BufferSize = 10; //DMA缓存大小,存放10次采样值DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址固定,接收一次数据后,设备地址禁止后移DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存地址不固定,接收多次数据后,目标内存地址后移DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord ; //外设数据单位,定义外设数据宽度为16位DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord ; //内存数据单位,HalfWord就是为16位DMA_InitStructure.DMA_Mode = DMA_Mode_Circular ; //DMA模式:循环传输DMA_InitStructure.DMA_Priority = DMA_Priority_High ; //DMA优先级:高DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //禁止内存到内存的传输DMA_Init(DMA1_Channel1, &DMA_InitStructure); //配置DMA1DMA_ITConfig(DMA1_Channel1,DMA_IT_TC, ENABLE);//使能传输完成中断 NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);DMA_Cmd(DMA1_Channel1,ENABLE);} //中断处理函数void DMA1_Channel1_IRQHandler(void){int sum=0;if(DMA_GetITStatus(DMA1_IT_TC1)!=RESET){//中断处理代码for(int i=0;i<10;i++){sum += ch1Value[i];}//均值滤波PWM1value = (int)map(sum/10,0,4092,1000,2000);sum=0;printf("%d\",PWM1value);printf("当前时间:%d:%d:%d\\",calendar.hour,calendar.min,calendar.sec);TIM_SetCompare2(TIM3,PWM1value);//输出给PWMDMA_ClearITPendingBit(DMA1_IT_TC1);//清除标志}}//GPIO配置,PA0void GPIOA_Init(void){GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA时钟 //PA6 作为模拟通道输入引脚 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;GPIO_Init(GPIOA, &GPIO_InitStructure);} //初始化ADC//这里我们仅以规则通道为例//我们默认将开启通道0~3 void Adc_Init(void){ ADC_InitTypeDef ADC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //使能ADC1通道时钟 //ADC1初始化ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //独立ADC模式ADC_InitStructure.ADC_ScanConvMode = DISABLE; //关闭扫描方式ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//关闭连续转换模式ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_CC2; //使用外部触发模式ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //采集数据右对齐ADC_InitStructure.ADC_NbrOfChannel = 1; //要转换的通道数目ADC_Init(ADC1, &ADC_InitStructure);RCC_ADCCLKConfig(RCC_PCLK2_Div6);//配置ADC时钟,为PCLK2的6分频,即12MHzADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_239Cycles5);//配置ADC1通道0为239.5个采样周期 //使能ADC、DMAADC_DMACmd(ADC1,ENABLE);ADC_Cmd(ADC1,ENABLE); ADC_ResetCalibration(ADC1);//复位校准寄存器while(ADC_GetResetCalibrationStatus(ADC1));//等待校准寄存器复位完成 ADC_StartCalibration(ADC1);//ADC校准while(ADC_GetCalibrationStatus(ADC1));//等待校准完成ADC_ExternalTrigConvCmd(ADC1, ENABLE);//设置外部触发模式使能} //获得ADC值//ch:通道值 0~9u16 Get_Adc(u8 ch) { //设置指定ADC的规则组通道,一个序列,采样时间ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 );//ADC1,ADC通道,采样时间为239.5个周期ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能指定的ADC1的软件转换启动功能while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束return ADC_GetConversionValue(ADC1);//返回最近一次ADC1规则组的转换结果} //ch:通道值 0~9,采样times次后作均值滤波u16 Get_Adc_Average(u8 ch,u8 times){u32 temp_val=0;u8 t;for(t=0;t<times;t++){temp_val+=Get_Adc(ch);delay_ms(5);}return temp_val/times;}//TIM3 PWM部分初始化 //PWM输出初始化//arr:自动重装值//psc:时钟预分频数void TIM3_PWM_Init(u16 arr,u16 psc){ GPIO_InitTypeDef GPIO_InitStructure;TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_OCInitTypeDef TIM_OCInitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);//使能定时器3时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE); //使能GPIO外设和AFIO复用功能模块时钟GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //Timer3部分重映射 TIM3_CH2->PB5 //设置该引脚为复用输出功能,输出TIM3 CH2的PWM脉冲波形GPIOB.5GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //TIM_CH2GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB //初始化TIM3TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_timTIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位//初始化TIM3 Channel2 PWM模式 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式1,计数值<自动重装载值时,输出高电平 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高TIM_OC2Init(TIM3, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM3 OC2 TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能TIM3在CCR2上的预装载寄存器 TIM_Cmd(TIM3, ENABLE); //使能TIM3} /*函数说明:仿Arduino,将一个数字从一个范围重新映射到另一个范围也就是说,fromLow的值将映射到toLow,fromlhigh到toHigh的值等等。*/float map(float value,float fromLow,float fromHigh,float toLow,float toHigh){return ((value-fromLow)*(toHigh-toLow)/(fromHigh-fromLow)+toLow);}

config.h-包含函数预定义和全局变量预定义

#ifndef __CONFIG_H#define __CONFIG_H#include "stm32f10x.h" //记得添加此头文件,因为config.c用到GPIO相关函数等#include "sys.h"extern volatile u16 ch1Value[10];//ADC采样值extern volatile u16 PWM1value;//控制PWM占空比void TIM2_Init(u16 arr,u16 psc);//TIM2定时器初始化void TIM3_PWM_Init(u16 arr,u16 psc);//PB5定时器初始化void DMA1_Init(void);void GPIOA_Init(void);void Adc_Init(void);//ADC1初始化u16 Get_Adc(u8 ch); //获取一次ADC的值u16 Get_Adc_Average(u8 ch,u8 times);//ADC采样值进行均值滤波float map(float value,float fromLow,float fromHigh,float toLow,float toHigh);//映射函数#endif

oled.c-包含各种显示函数和IIC初始化

// // 功能描述 : 0.69寸OLED 接口演示例程(STM32F103C8T6 IIC)// 说明: // ----------------------------------------------------------------// GND 电源地// VCC 接3.3v电源// SCL 接PB8(SCL)// SDA 接PB9(SDA) //? #include "oled.h"#include "stdlib.h"#include "oledfont.h" #include "delay.h"//OLED的显存//存放格式如下.//[0]0 1 2 3 ... 127//[1]0 1 2 3 ... 127//[2]0 1 2 3 ... 127//[3]0 1 2 3 ... 127//[4]0 1 2 3 ... 127//[5]0 1 2 3 ... 127//[6]0 1 2 3 ... 127//[7]0 1 2 3 ... 127 /

很赞哦!(699)