当前位置: 首页 新闻详细

舵机测试仪小型,【基础】STM32F103C8T6制作舵机测试仪详细图文教程

专业小程序设计开发——助力新电商新零售

电话+V:159999-78052,欢迎咨询舵机测试仪小型,[小程序设计与开发],[小程序投流与推广],[小程序后台搭建],[小程序整套源码打包],[为个体及小微企业助力],[电商新零售模式],[小程序运营推广及维护]

一、暴力小风扇用什么型号的无刷电机

3830。根据查询科技DOT显示,5045六叶螺旋桨,3830无刷电机,无刷电调,舵机测试仪,370马达支架。

【基础】STM32F103C8T6制作舵机测试仪详细图文教程

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

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

1.材料清单1.STM32F103C8T6蓝色开发板*1(黑色板也可以)

2.USB转TTL模块*1

3.ST-LINKV2仿真器下载器*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-LINKV2接法: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,再找STMicroelectronicsSTM32F1SeriesDeviceSupport,Driversand

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

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

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

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

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

点击Setting,打开Cortex-MTargetDriverSetup窗口,如果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=viewthreadtid=82875highlight=
%E8%88%B5%E6%9C%BA%E6%B5%8B%E8%AF%95%E4%BB%AA

控制无刷电调所用的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=viewthreadtid=277863extra=page=1

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

TIM3定时触发产生PWM信号,预分频72,频率1MHz,周期1us;自动装载值20000,故PWM周期1us*20000=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-LINKV2接法:GND电源地3V3接3.3vSWCLK接DCLKSWDIO接DIOPWM输出:PB5byBilibili蔡子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"intmain(){u8txt[16]={0};delay_init();//初始化延时函数NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置NVIC中断分组2,2位抢占优先级和2位子优先级usart_init(115200);//初始化串口1,波特率为115200TIM3_PWM_Init(19999,71);//预分频72,频率1MHz,周期1us;自动装载值20000,故PWM周期1us*20000TIM2_Init(499,71);//1MHz,每500us采集一次;可设置9us以上,但过小影响OLED显示DMA1_Init();//DMA初始化GPIOA_Init();//PA初始化Adc_Init();//ADC初始化RTC_Init();//RTC初始化OLED_Init();//初始化OLEDOLED_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"volatileu16ch1Value[10];//ADC采样值volatileu16PWM1value;//控制PWM占空比#defineADC1_DR_Address((u32)0x4001244C)//ADC1的地址//通用定时器2中断初始化//这里时钟选择为APB1的2倍,而APB1为36M//arr:自动重装值。//psc:时钟预分频数//这里使用的是定时器2控制ADC定时采样voidTIM2_Init(u16arr,u16psc){TIM_TimeBaseInitTypeDefTIM_TimeBaseStructure;TIM_OCInitTypeDefTIM_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配置voidDMA1_Init(void){DMA_InitTypeDefDMA_InitStructure;NVIC_InitTypeDefNVIC_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);}//中断处理函数voidDMA1_Channel1_IRQHandler(void){intsum=0;if(DMA_GetITStatus(DMA1_IT_TC1)!=RESET){//中断处理代码for(inti=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\r",calendar.hour,calendar.min,calendar.sec);TIM_SetCompare2(TIM3,PWM1value);//输出给PWMDMA_ClearITPendingBit(DMA1_IT_TC1);//清除标志}}//GPIO配置,PA0voidGPIOA_Init(void){GPIO_InitTypeDefGPIO_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~3voidAdc_Init(void){ADC_InitTypeDefADC_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~9u16Get_Adc(u8ch){//设置指定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));//等待转换结束returnADC_GetConversionValue(ADC1);//返回最近一次ADC1规则组的转换结果}//ch:通道值0~9,采样times次后作均值滤波u16Get_Adc_Average(u8ch,u8times){u32temp_val=0;u8t;for(t=0;t<times;t++){temp_val+=Get_Adc(ch);delay_ms(5);}returntemp_val/times;}//TIM3PWM部分初始化//PWM输出初始化//arr:自动重装值//psc:时钟预分频数voidTIM3_PWM_Init(u16arr,u16psc){GPIO_InitTypeDefGPIO_InitStructure;TIM_TimeBaseInitTypeDefTIM_TimeBaseStructure;TIM_OCInitTypeDefTIM_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//设置该引脚为复用输出功能,输出TIM3CH2的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的时间基数单位//初始化TIM3Channel2PWM模式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指定的参数初始化外设TIM3OC2TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable);//使能TIM3在CCR2上的预装载寄存器TIM_Cmd(TIM3,ENABLE);//使能TIM3}/*函数说明:仿Arduino,将一个数字从一个范围重新映射到另一个范围也就是说,fromLow的值将映射到toLow,fromlhigh到toHigh的值等等。*/floatmap(floatvalue,floatfromLow,floatfromHigh,floattoLow,floattoHigh){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"externvolatileu16ch1Value[10];//ADC采样值externvolatileu16PWM1value;//控制PWM占空比voidTIM2_Init(u16arr,u16psc);//TIM2定时器初始化voidTIM3_PWM_Init(u16arr,u16psc);//PB5定时器初始化voidDMA1_Init(void);voidGPIOA_Init(void);voidAdc_Init(void);//ADC1初始化u16Get_Adc(u8ch);//获取一次ADC的值u16Get_Adc_Average(u8ch,u8times);//ADC采样值进行均值滤波floatmap(floatvalue,floatfromLow,floatfromHigh,floattoLow,floattoHigh);//映射函数#endifoled.c-包含各种显示函数和IIC初始化

////功能描述:0.69寸OLED接口演示例程(STM32F103C8T6IIC)//说明://----------------------------------------------------------------//GND电源地//VCC接3.3v电源//SCL接PB8(SCL)//SDA接PB9(SDA)//?#include"oled.h"#include"stdlib.h"#include"oledfont.h"#include"delay.h"//OLED的显存//存放格式如下.//[0]0123...127//[1]0123...127//[2]0123...127//[3]0123...127//[4]0123...127//[5]0123...127//[6]0123...127//[7]0123...127/**********************************************//IICStart**********************************************/voidIIC_Start(void){OLED_SCLK_Set();OLED_SDIN_Set();OLED_SDIN_Clr();OLED_SCLK_Clr();}/**********************************************//IICStop**********************************************/voidIIC_Stop(void){OLED_SCLK_Set();//OLED_SCLK_Clr();OLED_SDIN_Clr();OLED_SDIN_Set();}voidIIC_Wait_Ack(void){OLED_SCLK_Set();OLED_SCLK_Clr();}/**********************************************//IICWritebyte**********************************************/voidWrite_IIC_Byte(unsignedcharIIC_Byte){unsignedchari;unsignedcharm,da;da=IIC_Byte;OLED_SCLK_Clr();for(i=0;i<8;i++){m=da;//OLED_SCLK_Clr();m=m0x80;if(m==0x80){OLED_SDIN_Set();}elseOLED_SDIN_Clr();da=da<<1;OLED_SCLK_Set();OLED_SCLK_Clr();}}/**********************************************//IICWriteCommand**********************************************/voidWrite_IIC_Command(unsignedcharIIC_Command){IIC_Start();Write_IIC_Byte(0x78);//Slaveaddress,SA0=0IIC_Wait_Ack();Write_IIC_Byte(0x00);//writecommandIIC_Wait_Ack();Write_IIC_Byte(IIC_Command);IIC_Wait_Ack();IIC_Stop();}/**********************************************//IICWriteData**********************************************/voidWrite_IIC_Data(unsignedcharIIC_Data){IIC_Start();Write_IIC_Byte(0x78);//D/C#=0;R/W#=0IIC_Wait_Ack();Write_IIC_Byte(0x40);//writedataIIC_Wait_Ack();Write_IIC_Byte(IIC_Data);IIC_Wait_Ack();IIC_Stop();}voidOLED_WR_Byte(unsigneddat,unsignedcmd){if(cmd){Write_IIC_Data(dat);}else{Write_IIC_Command(dat);}}/********************************************//fill_Picture********************************************/voidfill_picture(unsignedcharfill_Data){unsignedcharm,n;for(m=0;m<8;m++){OLED_WR_Byte(0xb0+m,0);//page0-page1OLED_WR_Byte(0x00,0);//lowcolumnstartaddressOLED_WR_Byte(0x10,0);//highcolumnstartaddressfor(n=0;n<128;n++){OLED_WR_Byte(fill_Data,1);}}}//坐标设置voidOLED_Set_Pos(unsignedcharx,unsignedchary){OLED_WR_Byte(0xb0+y,OLED_CMD);OLED_WR_Byte(((x0xf0)>>4)|0x10,OLED_CMD);OLED_WR_Byte((x0x0f),OLED_CMD);}//开启OLED显示voidOLED_Display_On(void){OLED_WR_Byte(0X8D,OLED_CMD);//SETDCDC命令OLED_WR_Byte(0X14,OLED_CMD);//DCDCONOLED_WR_Byte(0XAF,OLED_CMD);//DISPLAYON}//关闭OLED显示voidOLED_Display_Off(void){OLED_WR_Byte(0X8D,OLED_CMD);//SETDCDC命令OLED_WR_Byte(0X10,OLED_CMD);//DCDCOFFOLED_WR_Byte(0XAE,OLED_CMD);//DISPLAYOFF}//清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!!voidOLED_Clear(void){u8i,n;for(i=0;i<8;i++){OLED_WR_Byte(0xb0+i,OLED_CMD);//设置页地址(0~7)OLED_WR_Byte(0x00,OLED_CMD);//设置显示位置—列低地址OLED_WR_Byte(0x10,OLED_CMD);//设置显示位置—列高地址for(n=0;n<128;n++)OLED_WR_Byte(0,OLED_DATA);}//更新显示}//更新显存到OLEDu8OLED_GRAM[128][8];voidOLED_Refresh_Gram(void){u8i,n;for(i=0;i<8;i++){OLED_WR_Byte(0xb0+i,OLED_CMD);//设置页地址(0~7)OLED_WR_Byte(0x00,OLED_CMD);//设置显示位置—列低地址OLED_WR_Byte(0x10,OLED_CMD);//设置显示位置—列高地址for(n=0;n<128;n++)OLED_WR_Byte(OLED_GRAM[n][i],OLED_DATA);}}//画点//x:0~127//y:0~63//t:1填充0,清空voidOLED_DrawPoint(u8x,u8y,u8t){u8pos,bx,temp=0;if(x>127||y>63)return;//超出范围了.pos=7-y/8;bx=y%8;temp=1<<(7-bx);if(t)OLED_GRAM[x][pos]|=temp;elseOLED_GRAM[x][pos]=~temp;}//x1,y1,x2,y2填充区域的对角坐标//确保x1<=x2;y1<=y20<=x1<=1270<=y1<=63//dot:0,清空;1,填充voidOLED_Fill(u8x1,u8y1,u8x2,u8y2,u8dot){u8x,y;for(x=x1;x<=x2;x++){for(y=y1;y<=y2;y++)OLED_DrawPoint(x,y,dot);}OLED_Refresh_Gram();//更新显示}//在指定位置显示一个字符,包括部分字符//x:0~127//y:0~63//mode:0,反白显示;1,正常显示//size:选择字体12/16/24voidOLED_ShowChar(u8x,u8y,u8chr,u8size,u8mode){u8temp,t,t1;u8y0=y;u8csize=(size/8+((size%8)?1:0))*(size/2);//得到字体一个字符对应点阵集所占的字节数chr=chr-'';//得到偏移后的值for(t=0;t<csize;t++){if(size==12)temp=asc2_1206[chr][t];//调用1206字体elseif(size==16)temp=asc2_1608[chr][t];//调用1608字体elseif(size==24)temp=asc2_2412[chr][t];//调用2412字体elsereturn;//没有的字库for(t1=0;t1<8;t1++){if(temp0x80)OLED_DrawPoint(x,y,mode);elseOLED_DrawPoint(x,y,!mode);temp<<=1;y++;if((y-y0)==size){y=y0;x++;break;}}}}//m^n函数u32mypow(u8m,u8n){u32result=1;while(n--)result*=m;returnresult;}//显示2个数字//x,y:起点坐标//len:数字的位数//size:字体大小12/16/24//mode:模式0,填充模式;1,叠加模式//num:数值(0~4294967295);voidOLED_ShowNum(u8x,u8y,u32num,u8len,u8size){u8t,temp;u8enshow=0;for(t=0;t<len;t++){temp=(num/mypow(10,len-t-1))%10;if(enshow==0t<(len-1)){if(temp==0){OLED_ShowChar(x+(size/2)*t,y,'',size,1);continue;}elseenshow=1;}OLED_ShowChar(x+(size/2)*t,y,temp+'0',size,1);}}//显示字符串//x,y:起点坐标//size:字体大小12/16/24//*p:字符串起始地址voidOLED_ShowString(u8x,u8y,u8*p,u8size){while((*p<='~')(*p>=''))//判断是不是非法字符!{if(x>(128-(size/2))){x=0;y+=size;}if(y>(64-size)){y=x=0;OLED_Clear();}OLED_ShowChar(x,y,*p,size,1);x+=size/2;p++;}}//显示汉字voidOLED_ShowCHinese(u8x,u8y,u8no){u8t,adder=0;OLED_Set_Pos(x,y);for(t=0;t<16;t++){OLED_WR_Byte(Hzk[2*no][t],OLED_DATA);adder+=1;}OLED_Set_Pos(x,y+1);for(t=0;t<16;t++){OLED_WR_Byte(Hzk[2*no+1][t],OLED_DATA);adder+=1;}}/***********功能描述:显示显示BMP图片128×64起始点坐标(x,y),x的范围0~127,y为页的范围0~7*****************/voidOLED_DrawBMP(unsignedcharx0,unsignedchary0,unsignedcharx1,unsignedchary1,unsignedcharBMP[]){unsignedintj=0;unsignedcharx,y;if(y1%8==0)y=y1/8;elsey=y1/8+1;for(y=y0;y<y1;y++){OLED_Set_Pos(x0,y);for(x=x0;x<x1;x++){OLED_WR_Byte(BMP[j++],OLED_DATA);}}}//初始化SSD1306voidOLED_Init(void){GPIO_InitTypeDefGPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,ENABLE);//使能B端口和AFIO复用功能模块时钟GPIO_PinRemapConfig(GPIO_Remap_I2C1,ENABLE);//IIC1重映射->PB8,9GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8|GPIO_Pin_9;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//推挽输出GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//速度50MHzGPIO_Init(GPIOB,GPIO_InitStructure);//初始化GPIOB8,9GPIO_SetBits(GPIOB,GPIO_Pin_8|GPIO_Pin_9);delay_ms(800);OLED_WR_Byte(0xAE,OLED_CMD);//--显示关闭OLED_WR_Byte(0x00,OLED_CMD);//---设置最小列地址OLED_WR_Byte(0x10,OLED_CMD);//---设置最大列地址OLED_WR_Byte(0x40,OLED_CMD);//--setstartlineaddressOLED_WR_Byte(0xB0,OLED_CMD);//--setpageaddressOLED_WR_Byte(0x81,OLED_CMD);//contractcontrolOLED_WR_Byte(0xFF,OLED_CMD);//--128OLED_WR_Byte(0xA1,OLED_CMD);//setsegmentremapOLED_WR_Byte(0xA6,OLED_CMD);//--normal/reverseOLED_WR_Byte(0xA8,OLED_CMD);//--setmultiplexratio(1to64)OLED_WR_Byte(0x3F,OLED_CMD);//--1/32dutyOLED_WR_Byte(0xC0,OLED_CMD);//Com扫描方向,若显示的是镜对称,改为C8OLED_WR_Byte(0xD3,OLED_CMD);//-setdisplayoffsetOLED_WR_Byte(0x00,OLED_CMD);//OLED_WR_Byte(0xD5,OLED_CMD);//setoscdivisionOLED_WR_Byte(0x80,OLED_CMD);//OLED_WR_Byte(0xD8,OLED_CMD);//setareacolormodeoffOLED_WR_Byte(0x05,OLED_CMD);//OLED_WR_Byte(0xD9,OLED_CMD);//SetPre-ChargePeriodOLED_WR_Byte(0xF1,OLED_CMD);//OLED_WR_Byte(0xDA,OLED_CMD);//setcompinconfiguartionOLED_WR_Byte(0x12,OLED_CMD);//OLED_WR_Byte(0xDB,OLED_CMD);//setVcomhOLED_WR_Byte(0x30,OLED_CMD);//OLED_WR_Byte(0x8D,OLED_CMD);//setchargepumpenableOLED_WR_Byte(0x14,OLED_CMD);//OLED_WR_Byte(0xAF,OLED_CMD);//--turnonoledpanel}u8*itoa(intnum,u8*str,intradix){charindex[]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";//索引表unsignedunum;//存放要转换的整数的绝对值,转换的整数可能是负数inti=0,j,k;//i用来指示设置字符串相应位,转换之后i其实就是字符串的长度;转换后顺序是逆序的,有正负的情况,k用来指示调整顺序的开始位置;j用来指示调整顺序时的交换。//获取要转换的整数的绝对值if(radix==10num<0)//要转换成十进制数并且是负数{unum=(unsigned)-num;//将num的绝对值赋给unumstr[i++]='-';//在字符串最前面设置为'-'号,并且索引加1}elseunum=(unsigned)num;//若是num为正,直接赋值给unum//转换部分,注意转换后是逆序的do{str[i++]=index[unum%(unsigned)radix];//取unum的最后一位,并设置为str对应位,指示索引加1unum/=radix;//unum去掉最后一位}while(unum);//直至unum为0退出循环str[i]='\0';//在字符串最后添加'\0'字符,c语言字符串以'\0'结束。//将顺序调整过来if(str[0]=='-')k=1;//如果是负数,符号不用调整,从符号后面开始调整elsek=0;//不是负数,全部都要调整u8temp;//临时变量,交换两个值时用到for(j=k;j<=(i-1)/2;j++)//头尾一一对称交换,i其实就是字符串的长度,索引最大值比长度少1{temp=str[j];//头部赋值给临时变量str[j]=str[i-1+k-j];//尾部赋值给头部str[i-1+k-j]=temp;//将临时变量的值(其实就是之前的头部值)赋给尾部}returnstr;//返回转换后的字符串}oled.h-包含函数预定义和OLED显示所需的宏定义

///功能描述:0.69寸OLED接口演示例程(STM32F103C8T6IIC)//说明://----------------------------------------------------------------//GND电源地//VCC接3.3v电源//SCL接PB8(SCL)//SDA接PB9(SDA)//----------------------------------------------------------------//#ifndef__OLED_H#define__OLED_H#include"sys.h"#include"stdlib.h"#defineOLED_MODE0#defineSIZE8#defineXLevelL0x00#defineXLevelH0x10#defineMax_Column128#defineMax_Row64#defineBrightness0xFF#defineX_WIDTH128#defineY_WIDTH64//-----------------OLEDIIC端口定义----------------#defineOLED_SCLK_Clr()GPIO_ResetBits(GPIOB,GPIO_Pin_8)//SCL#defineOLED_SCLK_Set()GPIO_SetBits(GPIOB,GPIO_Pin_8)#defineOLED_SDIN_Clr()GPIO_ResetBits(GPIOB,GPIO_Pin_9)//SDA#defineOLED_SDIN_Set()GPIO_SetBits(GPIOB,GPIO_Pin_9)#defineOLED_CMD0//写命令#defineOLED_DATA1//写数据//OLED控制用函数voidOLED_WR_Byte(unsigneddat,unsignedcmd);voidOLED_Display_On(void);voidOLED_Display_Off(void);voidOLED_Init(void);voidOLED_Clear(void);voidOLED_Refresh_Gram(void);voidOLED_DrawPoint(u8x,u8y,u8t);voidOLED_Fill(u8x1,u8y1,u8x2,u8y2,u8dot);voidOLED_ShowChar(u8x,u8y,u8chr,u8size,u8mode);voidOLED_ShowNum(u8x,u8y,u32num,u8len,u8size);voidOLED_ShowString(u8x,u8y,u8*p,u8size);voidOLED_Set_Pos(unsignedcharx,unsignedchary);voidOLED_ShowCHinese(u8x,u8y,u8no);voidOLED_DrawBMP(unsignedcharx0,unsignedchary0,unsignedcharx1,unsignedchary1,unsignedcharBMP[]);voidfill_picture(unsignedcharfill_Data);voidIIC_Start(void);voidIIC_Stop(void);voidWrite_IIC_Command(unsignedcharIIC_Command);voidWrite_IIC_Data(unsignedcharIIC_Data);voidWrite_IIC_Byte(unsignedcharIIC_Byte);voidIIC_Wait_Ack(void);u8*itoa(intnum,u8*str,intradix);#endif其他代码基本就是正点原子官方的文件了,整个工程文件已上传天翼云盘:


https://cloud.189.cn/t/uYniA3iM3iei(访问码:g914)

6.实现效果串口调试助手查看串口输出


OLED显示

【WINDRISES MINIPROGRAM PROMOTION】尊享直接对接老板

电话+V: 159999-78052

专注于小程序推广配套流程服务方案。为企业及个人客户提供了高性价比的运营方案,解决小微企业和个体拓展客户的问题

舵机测试仪小型
发布人:nieanlengrishu0203 发布时间:2024-11-14