完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
扫一扫,分享给好友
本人新手小白,写这个文章完全是纪念自己第一个小项目,如有不足之处还请多多指教,谢谢!
先上图。 软件配置 本文主要用的编译软件为keil5,软件配置的部分可参考以下文章(文章也包括了烧录的部分)。《Keil5配置STM32F103C8T6》 硬件部分 以STM32F103c8t6的最小系统板为核心,配合HC-SR04超声波模块、SG90舵机以及一个0.96寸的IIC接口的OLED显示屏。当然还有若干的杜邦线及一个垃圾桶模型,模块固定部分可自行发挥。 1. 主控芯片 以STM32F103c8t6芯片为核心的最小系统板,实物图就如下所示,来源是淘宝。 关于STM32F103c8t6芯片本文就不加以介绍,可参考以下文章。《STM32F103C8T6初学笔记》 2. HC-SR04超声波模块 模块简介 HC-SR04超声波模块常用于机器人避障、物体测距、液位检测、公共安防、停车场检测等场所。HC-SR04超声波模块主要是由两个通用的压电陶瓷超声传感器,并加外围信号处理电路构成的。如图: 模块参数 1) 模块主要参数 ① 使用电压:DC—5V ② 静态电流:小于2mA ③ 电平输出:高5V ④ 电平输出:底0V ⑤ 感应角度:不大于15度 ⑥ 探测距离:2cm-450cm ⑦ 高精度 可达0.2cm 2) 模块引脚 超声波模块有4个引脚,分别为Vcc(电源+)、GND(接地)、 Trig(控制端)、 Echo(接收端);其中Vcc接上5V电源,GND接地, Trig(控制端)控制发出的超声波信号,Echo(接收端)接收反射回来的超声波信号。 工作原理 a.单片机引脚触发Trig测距,给至少 10us 的高电平信号; b.模块自动发送 8 个 40khz 的方波,自动检测是否有信号返回; c.有信号返回,通过 IO 输出一高电平,并单片机定时器计算高电平持续的时间; d.超声波从发射到返回的时间. 计算公式:测试距离=(高电平时间*声速(340M/S))/2; 简单来说,就是超声波模块发出声波信号,同时定时计数器器开始计时,声波信号在遇到障碍物后返回。采集到返回的声波信号后,模块输出一个高电平信号,相应配合的定时计数器停止计时,最后通过超声波在空气中的传递规律公式计算出障碍物的距离。 GPIO配置 HC-SR04C8T6芯片引脚GNDGNDVcc5VEchoPB7TrigPB83. SG90舵机 模块简介 舵机是一种位置(角度)伺服的驱动器,适用于那些需要角度不断变化并可以保持的控制系统。目前,在高档遥控玩具,如飞机、潜艇模型,遥控机器人中已经得到了普遍应用。如图: 模块参数 1) 模块主要参数 ① 死区设定:7us (7MHZ) ② 工作电压:4.8V-6V ③ 位置等级:1024级 ④ 脉冲控制精度为2us ⑤ 尺寸:21.5mmX11.8mmX22.7mm ⑥ 重量:9克 (1kg=1公斤=2斤) ⑦ 无负载速度:0.12秒/60度(4.8V) 0.002s/度 ⑧ 堵转扭矩:1.2-1.4公斤/厘米(4.8V) ⑨ 使用温度:-30~~+60摄氏度 2) 模块引脚 SG90模块有三个引脚,信号引脚(橙色)、Vcc(红色)及GND(棕色);在使用过程中,信号引脚与单片机输出PWM信号的引脚相连接,Vcc与电源+5V相连接,GND接地。 工作原理 SG90的工作原理是采用PWM控制的方式来进行舵机的操纵,主要是让板子产生一个20ms的脉冲信号,以0.5ms到2.5ms的高电平来控制舵机的角度。以180度角度伺服为例,那么对应的控制关系如下: 0.5ms-------------0度; 2.5% 对应函数中占空比为250 1.0ms------------45度; 5.0% 对应函数中占空比为500 1.5ms------------90度; 7.5% 对应函数中占空比为750 2.0ms-----------135度; 10.0% 对应函数中占空比为1000 2.5ms-----------180度; 12.5% 对应函数中占空比为1250 详细的舵机使用原理可参考《舵机使用基础(SG90模拟舵机和MG90S数字舵机为例)》 GPIO配置 SG90舵机C8T6芯片引脚GND(棕色)GNDVcc(红色)5V信号线(橙色)PA13. OLED显示屏 模块简介 OLED,即有机发光二极管( Organic Light Emitting Diode)。 OLED 由于同时具备自发光,不需背光源、对比度高、厚度薄、视角广、反应速度快、可用于挠曲性面板、使用温度范围广、构造及制程较简单等优异之特性,被认为是下一代的平面显示器新兴应用技术。如图: 模块参数 1) 模块主要参数 ① 尺寸:0.96 (inch) ② 工作电压:3.3V/5V ③ 高分辨率: 128x64 ④ 有效显示区域: 21.744x10.864(mm) ⑤ 模块尺寸: 27.3x27.8(mm) ⑥ 视角:>160° ⑦ 重量:15克 ⑧ OLED驱动芯片:SSD1306 ⑨ 功耗: 全亮约为25mA,全灭约为1.5mA ⑩ 使用温度:-20~~+70摄氏度 数据来源LCD wiki 2) 模块引脚 0.96寸OLED显示屏(IIC)有四个引脚,GND (接地)、 Vcc (电源+)、SCL OLED 的 D0 脚、SDA OLED 的 D1 脚。在使用过程中,Vcc接电源+3.3V(或+5V),GND接地, D0引脚,在 IIC 通信中为时钟管脚,D1引脚,在 IIC 通信中为数据管脚,接相应的GPIO口。 工作原理 本屏所用的驱动 IC 为 SSD1306;其具有内部升压功能;当然了本屏也可以选用外部升压,具体的请详查数据手册。SSD1306 控制器用1bit控制一个像素点显示。所以每个像素点只能显示黑白两色。其显示的RAM总共分为8页,每页有8行,每行128个像素点。设置像素点数据时,需要指定页地址,再分别指定列低地址跟列高地址,所以每次同时设置垂直方向的8个像素点。为了能够灵活控制任意任意位置的像素点,软件上先设置一个设置一个和RAM一样大小的全局一维数组,先将像素点数据设置到全局数组中,此过程采用或、与操作保证之前写入全局数组的数据不受破坏,然后将全局数组的数据写入到显示RAM中,这样就可以通过OLED显示出来了。 GPIO配置 OLED显示屏C8T6芯片引脚GNDGNDVcc3.3VSCLPA5SDAPA7软件部分 HC-SR04超声波代码 #include "hc-sr04.h"uint count = 0;// Set NVICvoid NVIC_Config(void){ NVIC_InitTypeDef NVIC_InitStructer; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC_InitStructer.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructer.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructer.NVIC_IRQChannelCmd = ENABLE; NVIC_InitStructer.NVIC_IRQChannel = TIM2_IRQn; NVIC_Init(&NVIC_InitStructer);}/*HC-SR04 GPIO TIM3*/void HC_SR04_init(void){ GPIO_InitTypeDef GPIO_InitStructer; TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructer; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); /*TRIG PB8*/ GPIO_InitStructer.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructer.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_InitStructer.GPIO_Pin = HCSR04_TRIG; GPIO_Init(HCSR04_PORT, &GPIO_InitStructer); /*ECOH PB7*/ GPIO_InitStructer.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入 GPIO_InitStructer.GPIO_Pin = HCSR04_ECHO; GPIO_Init(HCSR04_PORT, &GPIO_InitStructer); /*定时器TIM3初始化*/ TIM_DeInit(TIM3); TIM_TimeBaseInitStructer.TIM_Period = 999; //计数到1000为1ms TIM_TimeBaseInitStructer.TIM_Prescaler = 71; //1M的计数频率 1us计数 TIM_TimeBaseInitStructer.TIM_ClockDivision = TIM_CKD_DIV1; //不分频 TIM_TimeBaseInitStructer.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructer); TIM_ClearFlag(TIM3, TIM_FLAG_Update); // 清除中断更新 TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); // 打开定时器更新中断 NVIC_Config(); TIM_Cmd(TIM3, DISABLE); }/*测距部分*/float Count_Dist(void){ float distance = 0, sum = 0; uint16_t time; uint i = 0; while(i < 5) { GPIO_SetBits(HCSR04_PORT, HCSR04_TRIG); delay_us(20); GPIO_ResetBits(HCSR04_PORT, HCSR04_TRIG); while(GPIO_ReadInputDataBit(HCSR04_PORT, HCSR04_ECHO) == 0);//回响信号出现 TIM_Cmd(TIM3, ENABLE); //打开定时器 i += 1; while(GPIO_ReadInputDataBit(HCSR04_PORT, HCSR04_ECHO) == 1); //回响信号消失 TIM_Cmd(TIM3,DISABLE); //关闭定时器 time = TIM_GetCounter(TIM3); //获取TIM3计数值 distance = (time + count*1000)/58.0; //通过回响计算距离 sum = distance + sum; //五次结果相加 TIM3->CNT = 0; //TIM3清零 count = 0; //中断溢出次数清零 delay_ms(10); } distance = sum/5; //取5次的平均值 return distance;}void TIM3_IRQHandler(void) { if(TIM_GetITStatus(TIM3,TIM_IT_Update) != RESET) { TIM_ClearITPendingBit(TIM3, TIM_IT_Update); //?????? count++; }}SG90舵机代码 #include "sg90.h"void SG90_pwm_init(void){ GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; TIM_OCInitTypeDef TIM_OCInitStructure; /* 开启时钟 */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); /* 配置GPIO 选择GPIOA_1 */ GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;// PA1 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//推挽输出 GPIO_Init(GPIOA,&GPIO_InitStructure); //TIM2定时初始化 TIM_TimeBaseInitStructure.TIM_Period = 199; //PWM 频率=72000/(199+1)=36Khz TIM_TimeBaseInitStructure.TIM_Prescaler = 7199;//设置TIM2预分频 TIM_TimeBaseInitStructure.TIM_ClockDivision = 0;//时钟分割:TDTS = Tck_tim TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM2向上计数 TIM_TimeBaseInit(TIM2, & TIM_TimeBaseInitStructure); //PWM初始化 TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//PWM使能输出 TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low; TIM_OC2Init(TIM2,&TIM_OCInitStructure); TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);//使能TIM2在CCR1上的预装载寄存器 TIM_Cmd(TIM2,ENABLE);//使能TIM2外设}显示屏代码 由于显示屏的代码过于冗长,可参考中景园电子的0.96寸显示屏代码,这里对本项目修改的部分进行演示。首先讲解汉字取模的过程: ① 打开取模软件,然后模式选择字符模式,然后点击选项 ② 汉字取模设置如下,点击确定 ③ 在红框内输入要取模的汉字,然后点击生成字模 讲完怎么取模后,针对本项目需要的字进行取模。 显示屏主要显示垃圾桶的状态及障碍物的距离,因此需要显示的文字为“垃圾桶:开关距离为:”。 {0x20,0x20,0x20,0xFF,0x20,0x20,0x10,0x90,0x11,0x16,0x10,0x10,0xD0,0x10,0x00,0x00},{0x10,0x30,0x10,0x0F,0x08,0x48,0x40,0x41,0x5E,0x40,0x70,0x4E,0x41,0x40,0x40,0x00},/*"垃",0*//* (16 X 16 , ?? )*/{0x20,0x20,0x20,0xFF,0x20,0x22,0x02,0xFE,0x02,0x02,0x62,0x5A,0x46,0xC0,0x00,0x00},{0x08,0x18,0x08,0x07,0x44,0x34,0x8E,0x81,0x46,0x28,0x10,0x28,0x46,0x81,0x80,0x00},/*"圾",1*//* (16 X 16 , ?? )*/{0x10,0x90,0xFF,0x90,0x10,0xE2,0x22,0x2A,0x2A,0xF2,0x2A,0x26,0x22,0xE0,0x00,0x00},{0x06,0x01,0xFF,0x00,0x01,0xFF,0x09,0x09,0x09,0x7F,0x09,0x49,0x89,0x7F,0x00,0x00},/*"桶",2*//* (16 X 16 , ?? )*/{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},{0x00,0x00,0x36,0x36,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*":",3*//* (16 X 16 , ?? )*/{0x80,0x82,0x82,0x82,0xFE,0x82,0x82,0x82,0x82,0x82,0xFE,0x82,0x82,0x82,0x80,0x00},{0x00,0x80,0x40,0x30,0x0F,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00},/*"开",4*//* (16 X 16 , ?? )*/{0x00,0x00,0x10,0x11,0x16,0x10,0x10,0xF0,0x10,0x10,0x14,0x13,0x10,0x00,0x00,0x00},{0x81,0x81,0x41,0x41,0x21,0x11,0x0D,0x03,0x0D,0x11,0x21,0x41,0x41,0x81,0x81,0x00},/*"关",5*//* (16 X 16 , ?? )*/{0x00,0x3E,0x22,0xE2,0x22,0x3E,0x00,0xFE,0x22,0x22,0x22,0x22,0x22,0xE2,0x02,0x00},{0x20,0x3F,0x20,0x1F,0x11,0x11,0x00,0x7F,0x44,0x44,0x44,0x44,0x44,0x47,0x40,0x00},/*"距",6*//* (16 X 16 , ?? )*/{0x04,0x04,0x04,0xF4,0x84,0xD4,0xA5,0xA6,0xA4,0xD4,0x84,0xF4,0x04,0x04,0x04,0x00},{0x00,0xFE,0x02,0x02,0x12,0x3A,0x16,0x13,0x12,0x1A,0x32,0x42,0x82,0x7E,0x00,0x00},/*"离",7*//* (16 X 16 , ?? )*/{0x00,0x20,0x22,0x2C,0x20,0x20,0xE0,0x3F,0x20,0x20,0x20,0x20,0xE0,0x00,0x00,0x00},{0x80,0x40,0x20,0x10,0x08,0x06,0x01,0x00,0x01,0x46,0x80,0x40,0x3F,0x00,0x00,0x00},/*"为",8*//* (16 X 16 , ?? )*/{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},{0x00,0x00,0x36,0x36,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*":",9*//* (16 X 16 , ?? )*/根据需要的文字,写入部分显示屏的代码: void LEDSHOW1(void){ OLED_ShowChinese(18,8,0,16);//垃 OLED_ShowChinese(36,8,1,16);//圾 OLED_ShowChinese(54,8,2,16);//桶 OLED_ShowChinese(72,8,3,16);//: OLED_ShowChinese(18,40,6,16);//距 OLED_ShowChinese(36,40,7,16);//离 OLED_ShowChinese(54,40,8,16);//为 OLED_ShowChinese(72,< |
|
|
|
只有小组成员才能发言,加入小组>>
2386 浏览 0 评论
8910 浏览 4 评论
36487 浏览 19 评论
4981 浏览 0 评论
24307 浏览 34 评论
1375浏览 2评论
1629浏览 1评论
2017浏览 1评论
1441浏览 0评论
387浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 07:36 , Processed in 1.241598 second(s), Total 79, Slave 62 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号