文章目次
概要
本项目接纳模块化编程
一、USART1 与 USART3 的运用
USART1 和 USART3 主要负责数据的传输。我们可以通过它们与其他装备举行通讯,实现小狗与外界的互动(STM32 的 USART1 和 USART3 通常会有默认的引脚分配)。见下图
二、PWM 的功能实现
利用 PWM 技术,我们可以精确控制小狗的动作,比如通过调整占空比来模拟小狗的行走结果。
三、TIM 的应用
PWM(脉宽调制)的实现通常必要使用定时器(TIM)来提供精确的时间基准。定时器可以产生周期性的时钟信号,通过对定时器的配置,可以控制 PWM 信号的周期和占空比。利用定时器的计数功能,我们可以在特定的时间点切换输出电平,从而实现不同占空比的 PWM 信号。
四、I2C 控制 OLED
I2C 是毗连 OLED 显示屏的重要方式。通过 I2C 协议,我们能够将小狗的图像和动画数据正确地传输到显示屏上,使其生动呈现。
整体架构流程
通过串口对蓝牙和语音识别功能举行接收和发送,从而实现对单片机的控制。通过 PWM 实现对舵机的控制。通过II2通讯对 OLED 屏举行控制。
技术名词表明
PWM:脉冲宽度调制,通过调节脉冲的宽度来控制信号的平均值。
TIM:定时器,用于产生定时信号或举行时间丈量。
USART:通用同步/异步收发器,用于串行数据通讯。“TX”的全称是“Transmit”(发送),“RX”的全称是“Receive”(接收)。
II2:这个不太明确详细含义,大概是某种特定的标识或参数。
使能:意思是使某一功能或操纵得以启用、生效或实现。
它通常用于描述开启或激活某个特定的本领或机制。
遍历:按照肯定的规则依次访问和处理数据结构中的每个元素的过程。
它就像是逐一查抄数据结构中的每一项,确保不遗漏任何一个元素。
常见的数据结构遍历包括数组遍历、链表遍历、树结构遍历等。通过遍历,可以对数据举行各种操纵,如读取、修改、统计等。
技术细节
蓝牙部分
在界说 TX(发送)引脚时,通常初始化为推挽输出模式;而界说 RX(接收)引脚时,一般初始化为浮空输入或上拉输入模式。设置PA9,PA10分别为TX,RX.
- #include "stm32f10x.h" // Device header
- #include <stdio.h>
- #include <stdarg.h>
- #include "Delay.h"
- #include <stdlib.h>
- uint8_t USART1_RxData; //存储从串口接收到的数据的变量
- uint8_t USART1_RxFlag; //指示串口接收状态的变量,通常用于表示是否有新的数据接收到、接收是否完成等状态信息。
- void USART1_Init(void)
- {
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启时钟
- GPIO_InitTypeDef GPIO_InitStructure; //定义结构体
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出,TX
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//表示输入上拉模式。
- 在这种模式下,对应引脚被配置为输入模式,并且内部有上拉电阻,使得引脚在没有外部输入时保持高电平。
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
-
- USART_InitTypeDef USART_InitStructure;
- USART_InitStructure.USART_BaudRate = 9600; //波特率
- USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//这里是选择不用硬件流控制,硬件流控制是一种数据传输的控制方式。它通过使用特定的硬件信号线(如 RTS/CTS 等)来在发送方和接收方之间进行通信,以协调数据的发送和接收速度,确保数据传输的准确性和稳定性,避免数据丢失或错乱。以下情况通常会使用硬件流控制:
- 高速数据传输:当数据传输速率较高,需要更精确地控制数据发送和接收时。
- 对数据准确性要求高:在一些关键应用中,为了保证数据的完整性,会采用硬件流控制。
- 长距离传输:在信号容易受到干扰的长距离传输中,硬件流控制有助于提高传输的可靠性。
- USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; //两种模式均选择
- USART_InitStructure.USART_Parity = USART_Parity_No; // Parity 的意思是奇偶,这里是选择不需要奇偶校验,奇偶校验是一种简单的校验方法,用于检测数据在传输或存储过程中是否发生错误。
- 它通过在数据编码中添加一位校验位,使数据中“1”的个数为奇数(奇校验)或偶数(偶校验)。接收方通过检查校验位来判断数据是否正确。
- USART_InitStructure.USART_StopBits = USART_StopBits_1; //停止位1位
- USART_InitStructure.USART_WordLength = USART_WordLength_8b; //数据位8位,8b就是8bit。
- USART_Init(USART1, &USART_InitStructure);
-
- USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //开启中断
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //配置 NVIC 优先级分组为 2。
- NVIC_InitTypeDef NVIC_InitStructure;
- NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //使能中断、抢占优先级和响应优先级都设置为 1。抢占优先级:指的是中断能够抢占其他低优先级中断的能力。具有较高抢占优先级的中断可以先被执行,从而中断正在执行的低优先级中断。
- 响应优先级:也称为子优先级,它决定了在具有相同抢占优先级的中断同时发生时的执行顺序。响应优先级较高的中断会先被处理。对比串口3,第一个串口的抢占优先级和响应优先级都为 1,意味着它在中断处理中的优先级相对较低。
- 第三个串口的抢占优先级为 1,与第一个串口相同,但响应优先级设置为 3,相对较高。这意味着在相同抢占优先级的中断中,第二个串口的中断会优先得到响应和处理
- NVIC_Init(&NVIC_InitStructure);
-
- USART_Cmd(USART1, ENABLE); //使能
- }
- //下面是一些函数
- USART1_SendByte 和 USART1_SendArray 函数用于通过串口发送单个字节或数组数据。
- USART1_SendString 函数用于发送字符串数据。
- Serial_Pow 函数用于计算幂运算。
- USART1_SendNumber 函数用于发送数字。
- USART1_fputc 函数用于将字符输出到串口,使其可以像标准输出一样使用。
- USART1_Printf 函数用于格式化并发送数据到串口。
- USART1_GetRxFlag 和 USART1_GetRxData 函数用于获取接收标志和接收数据。
- USART1_IRQHandler 函数是串口中断处理函数,用于处理接收数据的事件。
- void USART1_SendByte(uint8_t Byte)
- {
- USART_SendData(USART1, Byte); //将指定的字节数据写入串口 1 的发送寄存器。
- while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); //这是一个等待循环,它会一直等待,直到串口 1 的发送缓冲区为空(即发送完成标志 USART_FLAG_TXE 被设置)。
- }
- void USART1_SendArray(uint8_t *Array, uint16_t Length)
- {
- uint16_t i;
- for (i = 0; i < Length; i ++)
- {
- USART1_SendByte(Array[i]);
- }
- }//uint16_t i:定义一个循环变量 i。
- for (i = 0; i < Length; i ++):通过循环,从数组的第一个元素开始,依次将每个元素作为一个字节发送出去。
- 在每次循环中,通过调用 USART1_SendByte(Array[i]),将当前数组元素发送出去。
- void USART1_SendString(char *String)
- {
- uint8_t i;
- for (i = 0; String[i] != '\0'; i ++)
- {
- USART1_SendByte(String[i]);
- }
- }
- //uint8_t i:定义一个用于遍历字符串的索引变量i。
- for (i = 0; String[i]!= '\0'; i ++):这是一个循环,从字符串的开头开始,一直到遇到字符串的结束标志('\0')为止。
- 在循环中,通过USART1_SendByte(String[i]),将字符串的每个字符依次作为一个字节发送出去。这样就实现了将整个字符串通过串口发送出去的功能。
- uint32_t Serial_Pow(uint32_t X, uint32_t Y)
- {
- uint32_t Result = 1;
- while (Y --)
- {
- Result *= X;
- }
- return Result;
- }
- //Serial_Pow 函数用于计算一个数的指定次幂。
- uint32_t Result = 1:初始化结果为 1。
- while (Y --):这是一个循环,循环次数为 Y 次。
- 在循环中,通过不断将当前结果乘以 X,来计算幂值。每次循环后,Y 的值减 1。
- 当循环结束后,返回计算得到的幂值。
- void USART1_SendNumber(uint32_t Number, uint8_t Length)
- {
- uint8_t i;
- for (i = 0; i < Length; i ++)
- {
- USART1_SendByte(Number / Serial_Pow(10, Length - i - 1) % 10 + '0');
- }
- }
- //uint8_t i:定义一个循环变量 i。
- for (i = 0; i < Length; i ++):通过循环,从数字的高位到低位,逐位处理。
- 在每次循环中,计算当前位的数值,即 Number 除以 Serial_Pow(10, Length - i - 1) 取余后再加上 '0',将其转换为字符。然后使用 USART1_SendByte 发送该字符。这样就实现了将数字按位发送的效果。
- int USART1_fputc(int ch, FILE *f)
- {
- USART1_SendByte(ch);
- return ch;
- }
- //USART1_fputc 函数:
- USART1_SendByte(ch):将输入的字符 ch 通过 USART1_SendByte 发送出去。
- return ch:返回输入的字符。
- void USART1_Printf(char *format, ...)
- {
- char String[100];
- va_list arg;
- va_start(arg, format);
- vsprintf(String, format, arg);
- va_end(arg);
- USART1_SendString(String);
- }//定义一个字符数组 String[100] 用于存储格式化后的字符串。
- 使用 va_list 和相关函数来处理可变参数,将格式化后的字符串存储到 String 中。
- 最后通过 USART1_SendString 将格式化后的字符串发送出去
- uint8_t USART1_GetRxFlag(void)
- {
- if (USART1_RxFlag == 1)
- {
- USART1_RxFlag = 0;
- return 1;
- }
- return 0;
- }
- //检查 USART1_RxFlag 是否为 1,如果是则将其重置为 0,并返回 1,表示接收到数据。
- uint8_t USART1_GetRxData(void)
- {
- return USART1_RxData;
- }//返回接收到的串口数据 USART1_RxData。
- void USART1_IRQHandler(void)
- {
- if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
- {
- USART1_RxData = USART_ReceiveData(USART1);
- USART1_RxFlag = 1;
- USART_ClearITPendingBit(USART1, USART_IT_RXNE);//清除中断挂起位。
-
-
- }
- }
- //在中断处理函数中,当接收到串口数据(USART_IT_RXNE 标志位被设置为 SET)时,获取接收到的数据并设置 USART1_RxFlag 为 1。
复制代码 语言控制部分(与上文代码大体结构雷同,上文代码中均有表明,此段代码不做表明,参考上文即可理解)
- #include "stm32f10x.h" // Device header
- #include <stdio.h>
- #include <stdarg.h>
- #include "Delay.h"
- #include <stdlib.h>
- uint8_t USART3_RxData;
- uint8_t USART3_RxFlag;
- void USART3_Init(void)
- {
-
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
- GPIO_InitTypeDef GPIO_InitStructure;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
- GPIO_Init(GPIOB, &GPIO_InitStructure);
-
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
- GPIO_Init(GPIOB, &GPIO_InitStructure);
-
-
- USART_InitTypeDef USART_InitStructure;
- USART_InitStructure.USART_BaudRate = 9600;
- USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
- USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
- USART_InitStructure.USART_Parity = USART_Parity_No;
- USART_InitStructure.USART_StopBits = USART_StopBits_1;
- USART_InitStructure.USART_WordLength = USART_WordLength_8b;
- USART_Init(USART3, &USART_InitStructure);
- USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
- NVIC_InitTypeDef NVIC_InitStructure;
- NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
- NVIC_Init(&NVIC_InitStructure);
-
-
- USART_Cmd(USART3, ENABLE);
- }
- uint8_t USART3_GetRxFlag(void)
- {
- if (USART3_RxFlag == 1)
- {
- USART3_RxFlag = 0;
- return 1;
- }
- return 0;
- }
- uint8_t USART3_GetRxData(void)
- {
- return USART3_RxData;
- }
- void USART3_IRQHandler(void)
- {
- if (USART_GetITStatus(USART3, USART_IT_RXNE) == SET)
- {
- USART3_RxData = USART_ReceiveData(USART3);
- USART3_RxFlag = 1;
- USART_ClearITPendingBit(USART3, USART_IT_RXNE);
-
- }
- }
复制代码 OLED部分
因内容太多,放于下一期文章,本文侧重点在于控制体系
舵机部分
舵机原理见(【STM32(意法半导体推出的32位微控制器)通过HC-05主从机一体蓝牙模块实现对舵机(SG90)的控制(含源码) - CSDN App】http://t.csdnimg.cn/O6hDl)
PWM、Servo、Movement三个文件共同为驱动舵机服务
PA6:右前脚,PA7:右后脚,PB0:左前脚,PB1:左后脚
PWM
- #include "stm32f10x.h" // Device header
- void PWM_Init(void)
- {
- // 使能 TIM3 的时钟
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
- // 使能 GPIOA 的时钟
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
- // 使能 GPIOB 的时钟
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
- // GPIO 初始化结构体设置
- GPIO_InitTypeDef GPIO_InitStructure;
- // 设置 GPIO 模式为复用推挽输出
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- // 设置 GPIO 引脚为 PA6 和 PA7
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
- // 设置 GPIO 速度为 50MHz
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- // 初始化 GPIOA
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- // 设置 GPIO 引脚为 PB0 和 PB1
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;
- // 初始化 GPIOB
- GPIO_Init(GPIOB, &GPIO_InitStructure);
- // 配置 TIM3 内部时钟
- TIM_InternalClockConfig(TIM3);
- // TIM 时间基准初始化结构体设置
- TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
- // 设置时钟分频为 1
- TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
- // 设置计数器模式为向上计数
- TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
- // 设置周期为 20000 - 1
- TIM_TimeBaseInitStructure.TIM_Period = 20000 - 1;
- // 设置预分频器为 72 - 1
- TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1;
- // 设置重复计数器为 0
- TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
- // 初始化 TIM3 的时间基准
- TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
- // TIM 输出比较初始化结构体设置
- TIM_OCInitTypeDef TIM_OCInitStructure;
- // 结构体初始化
- TIM_OCStructInit(&TIM_OCInitStructure);
- // 设置输出比较模式为 PWM1
- TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
- // 设置输出极性为高
- TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
- // 设置输出使能为启用
- TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
- // 设置脉冲宽度为 0
- TIM_OCInitStructure.TIM_Pulse = 0;
- // 初始化 TIM3 的通道 2
- TIM_OC2Init(TIM3, &TIM_OCInitStructure);
- // 初始化 TIM3 的通道 3
- TIM_OC3Init(TIM3, &TIM_OCInitStructure);
- // 初始化 TIM3 的通道 1
- TIM_OC1Init(TIM3, &TIM_OCInitStructure);
- // 初始化 TIM3 的通道 4
- TIM_OC4Init(TIM3, &TIM_OCInitStructure);
- // 使能 TIM3
- TIM_Cmd(TIM3, ENABLE);
- }
- void PWM_SetCompare1(uint16_t Compare)
- {
- TIM_SetCompare1(TIM3, Compare);
- }
- void PWM_SetCompare2(uint16_t Compare)
- {
- TIM_SetCompare2(TIM3, Compare);
- }
- void PWM_SetCompare3(uint16_t Compare)
- {
- TIM_SetCompare3(TIM3, Compare);
- }
- void PWM_SetCompare4(uint16_t Compare)
- {
- TIM_SetCompare4(TIM3, Compare);
- }
- //设置比较值的主要目的是控制 PWM(脉冲宽度调制)信号的占空比。
- 通过改变比较值,可以调整输出信号高电平的持续时间,从而实现对被控对象的精确控制,比如调节电机的转速、灯光的亮度等。不同的比较值对应着不同的占空比,进而影响输出的效果。
复制代码 SERVO
Angle 是舵机角度,范围:0~180
- #include "stm32f10x.h" // Device header // 包含 STM32 芯片相关的头文件
- #include "PWM.h" // 包含 PWM 相关的头文件
- void Servo_Init(void) // 定义 Servo_Init 函数
- {
- PWM_Init(); // 调用 PWM_Init 函数进行初始化
- }
- void Servo_SetAngle1(float Angle) // 定义 Servo_SetAngle1 函数,用于设置角度 1
- {
- PWM_SetCompare1(Angle / 180 * 2000 + 500); // 根据输入的角度计算比较值并设置
- }
- void Servo_SetAngle2(float Angle) // 定义 Servo_SetAngle2 函数,用于设置角度 2
- {
- PWM_SetCompare2(Angle / 180 * 2000 + 500); // 同上
- }
- void Servo_SetAngle3(float Angle) // 定义 Servo_SetAngle3 函数,用于设置角度 3
- {
- PWM_SetCompare3(Angle / 180 * 2000 + 500); // 同上
- }
- void Servo_SetAngle4(float Angle) // 定义 Servo_SetAngle4 函数,用于设置角度 4
- {
- PWM_SetCompare4(Angle / 180 * 2000 + 500); // 同上
- }
- uint8_t Servo_GetAngle1(void) // 定义 Servo_GetAngle1 函数,用于获取角度 1
- {
- return (TIM_GetCapture1(TIM3) - 500) * 180 / 2000; // 通过定时器捕获值计算并返回角度
- }
- uint8_t Servo_GetAngle2(void) // 定义 Servo_GetAngle2 函数,用于获取角度 2
- {
- return (TIM_GetCapture2(TIM3) - 500) * 180 / 2000; // 同上
- }
- uint8_t Servo_GetAngle3(void) // 定义 Servo_GetAngle3 函数,用于获取角度 3
- {
- return (TIM_GetCapture3(TIM3) - 500) * 180 / 2000; // 同上
- }
- uint8_t Servo_GetAngle4(void) // 定义 Servo_GetAngle4 函数,用于获取角度 4
- {
- return (TIM_GetCapture4(TIM3) - 500) * 180 / 2000; // 同上
- }
- //这样的计算是为了将角度范围转换为相应的定时器比较值,从而实现对 PWM 信号占空比的精确控制,以达到控制伺服o 电机转动角度的目的。
复制代码 MOVEMENT(此段函数是设置一些角度)
各器件共同部分(各种器件连在一起完成某个动作)
- #include "stm32f10x.h" // Device header
- #include "stdlib.h"
- #include "LED.h"
- #include "Delay.h"
- #include "OLED.h"
- #include "Servo.h"
- #include "PWM.h"
- #include "Movement.h"
- #include "usart1.h"
- #include "usart3.h"
- #include "stdio.h"
- extern uint8_t move_mode1 ;
- extern uint8_t move_mode3 ;
- extern uint8_t move_mode ;
- extern uint8_t previous_mode ;
- void mode_forward(void)
- {
- OLED_ShowImage(0, 0, 128, 64, BMP2);
- move_forward();
- LED13_Turn();
- previous_mode = move_mode;
-
- }
- void mode_behind(void)
- {
- OLED_ShowImage(0, 0, 128, 64, BMP2);
- move_behind();
- LED13_Turn();
- previous_mode = move_mode;
-
- }
- void mode_left(void)
- {
- OLED_ShowImage(0, 0, 128, 64, BMP3);
- move_left();
- LED13_Turn();
- previous_mode = move_mode;
-
-
- }
- void mode_right(void)
- {
- OLED_ShowImage(0, 0, 128, 64, BMP4);
- move_right();
- LED13_Turn();
- previous_mode = move_mode;
- }
- void mode_swing_qianhou(void)
- {
- OLED_ShowImage(0, 0, 128, 64, BMP11);
- move_shake_qianhou();
- LED13_Turn();
- previous_mode = move_mode;
- }
- void mode_swing_zuoyou(void)
- {
- OLED_ShowImage(0, 0, 128, 64, BMP11);
- move_shake_zuoyou();
- LED13_Turn();
- previous_mode = move_mode;
- }
- void mode_dance(void)
- {
- OLED_ShowImage(0, 0, 128, 64, BMP5);
- move_dance();
- LED13_Turn();
- previous_mode = move_mode;
-
- }
- void mode_stand(void)
- {
- OLED_ShowImage(0, 0, 128, 64, BMP1);
- move_stand();
- LED13_Turn();
- previous_mode = move_mode;
- move_mode = '0';
-
- }
- void mode_slowstand(void)
- {
-
- OLED_ShowImage(0, 0, 128, 64, BMP1);
- move_slow_stand(previous_mode);
- LED13_Turn();
- previous_mode = move_mode;
- move_mode = '0';
- }
- void mode_strech(void)
- {
- OLED_ShowImage(0, 0, 128, 64, BMP1);
- move_slow_stand(previous_mode);
- OLED_ShowImage(0, 0, 128, 64, BMP2);
- move_stretch();
- OLED_ShowImage(0, 0, 128, 64, BMP12);
- LED13_Turn();
- previous_mode = move_mode;
- move_mode = '0';
-
- }
- void mode_hello(void)
- {
- if (previous_mode != '5' && previous_mode != 'D') {
- OLED_ShowImage(0, 0, 128, 64, BMP1);
- move_slow_stand(previous_mode);
- }
- OLED_ShowImage(0, 0, 128, 64, BMP12);
- int i;
- for(i=0;i<20;i++)
- {
- Servo_SetAngle1(90-i);
- Servo_SetAngle2(90+i);
- Servo_SetAngle4(90-i);
- Delay_ms(7);
- }
- for(i=0;i<40;i++)
- {
- Servo_SetAngle2(110+i);
- Servo_SetAngle4(70-i);
- Delay_ms(7);
- }
- for(i=0;i<60;i++)
- {
- Servo_SetAngle1(70+i);
- Delay_ms(4);
- }
- Delay_ms(50);
- Servo_SetAngle1(180);
- Delay_ms(400);
- Servo_SetAngle1(130);
- Delay_ms(400);
- Servo_SetAngle1(180);
- Delay_ms(400);
- Servo_SetAngle1(130);
- Delay_ms(400);
- Servo_SetAngle1(70);
- Delay_ms(500);
- LED13_Turn();
- previous_mode = move_mode;
- move_mode = '0';
- }
- void mode_twohands(void)
- {
- OLED_ShowImage(0, 0, 128, 64, BMP1);
- move_stand();
- move_two_hands();
- LED13_Turn();
- previous_mode = move_mode;
- move_mode = '0';
-
- }
- void mode_lanyao(void)
- {
- OLED_ShowImage(0, 0, 128, 64, BMP1);
- move_slow_stand(previous_mode);
- OLED_ShowImage(0, 0, 128, 64, BMP9);
- lan_yao();
- OLED_ShowImage(0, 0, 128, 64, BMP1);
- LED13_Turn();
- previous_mode = move_mode;
- move_mode = '0';
-
- }
- void mode_headup(void)
- {
- OLED_ShowImage(0, 0, 128, 64, BMP1);
- move_slow_stand(previous_mode);
- OLED_ShowImage(0, 0, 128, 64, BMP10);
- move_head_up();
- LED13_Turn();
- previous_mode = move_mode;
- move_mode = '0';
-
- }
- void mode_sleeppa(void)
- {
- if (previous_mode != '5' && previous_mode != 'q') {
- OLED_ShowImage(0, 0, 128, 64, BMP1);
- move_slow_stand(previous_mode);
- }
- if (rand()%2) {
- OLED_ShowImage(0, 0, 128, 64, BMP6);
- }
- else{
- OLED_ShowImage(0, 0, 128, 64, BMP8);
- }
- move_sleep_p();
- previous_mode = move_mode;
- move_mode = '0';
- }
- void mode_sleepwo(void)
- {
- if (previous_mode != '5' && previous_mode != 'q') {
- OLED_ShowImage(0, 0, 128, 64, BMP1);
- move_slow_stand(previous_mode);
- Delay_s(1);
- }
- if (rand()%2) {
- OLED_ShowImage(0, 0, 128, 64, BMP6);
- }
- else{
- OLED_ShowImage(0, 0, 128, 64 , BMP8);
- }
- move_sleep_w();
- previous_mode = move_mode;
- move_mode = '0';
-
- }
复制代码 主函数逻辑
LD3320串口版语音模块(需单独烧录)
放置开源代码中,不举行表明,可参考文章(http://【STM32F103C8T6与LD3320举行串口通讯控制LED灯的亮灭 - CSDN App】http://t.csdnimg.cn/8qo2F)
开源代码
通过网盘分享的文件:软件.zip
链接: https://pan.baidu.com/s/1lWq7ZRIU3ooZQUHlGB4-mg?pwd=2003 提取码: 2003
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |