舵轮时钟-STM32-28路PWM--ESP8266-NTP时间

1.STM32--PWM生成

STM32不具备如此多的PWM,因此采用软件定时器的方案实现:

使用hal库实现;

main.c

#include "main.h"#define close1 500#define open 1500#define close 2500// 定时器中断配置(以TIM2为例)
void TIM2_IRQ_Init(void) {time_init();
}// 初始化舵机GPIO
void Servo_GPIO_Init(void) {GPIO_InitTypeDef gpio_init_struct;__HAL_RCC_GPIOA_CLK_ENABLE();                   /* GPIOA时钟使能 */// 初始化GPIOA PA0-PA7gpio_init_struct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 |GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7| GPIO_PIN_8| GPIO_PIN_11;                   /* 引脚 */gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;            /* 推挽输出 */gpio_init_struct.Pull = GPIO_PULLUP;                    /* 上拉 */gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;          /* 高速 */HAL_GPIO_Init(GPIOA, &gpio_init_struct);       /* 初始化GPIOA引脚 */// 初始化GPIOA PB0-PB15	__HAL_RCC_GPIOB_CLK_ENABLE(); gpio_init_struct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 |GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7|GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 |GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;                   /* 引脚 */gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;            /* 推挽输出 */gpio_init_struct.Pull = GPIO_PULLUP;                    /* 上拉 */gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;          /* 高速 */HAL_GPIO_Init(GPIOB, &gpio_init_struct);       /* 初始化GPIOB引脚 */// 初始化GPIOA PC13-PA15	__HAL_RCC_GPIOB_CLK_ENABLE(); gpio_init_struct.Pin = GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;                   /* 引脚 */gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;            /* 推挽输出 */gpio_init_struct.Pull = GPIO_PULLUP;                    /* 上拉 */gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;          /* 高速 */HAL_GPIO_Init(GPIOC, &gpio_init_struct);       /* 初始化GPIOC引脚 */}// 设置舵机脉宽(通道0-29)
void Set_Servo_Pulse(uint8_t ch, uint16_t pulse_us) {if(ch >= SERVO_NUM) return;if(pulse_us < 500) pulse_us = 500;   // 限制最小脉宽if(pulse_us > 2500) pulse_us = 2500; // 限制最大脉宽servo[ch].pulse_us = pulse_us;       // 更新目标脉宽
}uint8_t TIME_HOUR_24h=0;
// 主函数
int main(void) {int XB=0;HAL_Init();                         /* 初始化HAL库 */sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */delay_init(72);                     /* 延时初始化 */led_init();		//PC13usart_init(115200);				//PA9/PA10// 初始化舵机GPIO结构体(示例部分引脚)servo[0].GPIOx = GPIOB; servo[0].GPIO_Pin = GPIO_PIN_0;servo[1].GPIOx = GPIOB; servo[1].GPIO_Pin = GPIO_PIN_1;servo[2].GPIOx = GPIOB; servo[2].GPIO_Pin = GPIO_PIN_5;servo[3].GPIOx = GPIOB; servo[3].GPIO_Pin = GPIO_PIN_6;servo[4].GPIOx = GPIOB; servo[4].GPIO_Pin = GPIO_PIN_7;servo[5].GPIOx = GPIOB; servo[5].GPIO_Pin = GPIO_PIN_8;servo[6].GPIOx = GPIOB; servo[6].GPIO_Pin = GPIO_PIN_9;servo[7].GPIOx = GPIOB; servo[7].GPIO_Pin = GPIO_PIN_10;servo[8].GPIOx = GPIOB; servo[8].GPIO_Pin = GPIO_PIN_11;servo[9].GPIOx = GPIOB; servo[9].GPIO_Pin = GPIO_PIN_12;servo[10].GPIOx = GPIOB; servo[10].GPIO_Pin = GPIO_PIN_13;servo[11].GPIOx = GPIOB; servo[11].GPIO_Pin = GPIO_PIN_14;servo[12].GPIOx = GPIOB; servo[12].GPIO_Pin = GPIO_PIN_15;servo[13].GPIOx = GPIOA; servo[13].GPIO_Pin = GPIO_PIN_0;servo[14].GPIOx = GPIOA; servo[14].GPIO_Pin = GPIO_PIN_1;servo[15].GPIOx = GPIOA; servo[15].GPIO_Pin = GPIO_PIN_2;servo[16].GPIOx = GPIOA; servo[16].GPIO_Pin = GPIO_PIN_3;servo[17].GPIOx = GPIOA; servo[17].GPIO_Pin = GPIO_PIN_4;servo[18].GPIOx = GPIOA; servo[18].GPIO_Pin = GPIO_PIN_5;servo[19].GPIOx = GPIOA; servo[19].GPIO_Pin = GPIO_PIN_6;servo[20].GPIOx = GPIOA; servo[20].GPIO_Pin = GPIO_PIN_7;servo[21].GPIOx = GPIOA; servo[21].GPIO_Pin = GPIO_PIN_8;servo[22].GPIOx = GPIOA; servo[22].GPIO_Pin = GPIO_PIN_11;// ... 继续初始化剩余28个舵机的GPIO信息Servo_GPIO_Init();    // 初始化GPIOTIM2_IRQ_Init();      // 配置定时器中断while(1) {// 在此添加舵机控制逻辑(示例:通道0摆动)switch  (g_usart1_rx_flag){case 0:
//					printf("AT+CWJAP_DEF=\"iPhone\",\"mm123456789\"\r\n");printf("AT+CWJAP=\"Mm\",\"mjmhyw15891443374!\"\r\n");	  		delay_ms(6000);break;case 20:printf("AT+CIPSNTPCFG=1,8,\"ntp1.aliyun.com\"\r\n");delay_ms(1000);break;case 10:printf("AT+CIPSNTPTIME?\r\n");delay_ms(100);break;case 1:printf("AT+CIPSNTPTIME?\r\n");delay_ms(50);if(g_usart1_rx_flag==1){if((TIME_HOUR_24h<7)||(TIME_HOUR_24h>22));else{XB=0;switch (time_min[1]){case 0:Set_Servo_Pulse(XB+0, open);Set_Servo_Pulse(XB+1, open);Set_Servo_Pulse(XB+2, open);Set_Servo_Pulse(XB+3, open);Set_Servo_Pulse(XB+4, open);Set_Servo_Pulse(XB+5, open);Set_Servo_Pulse(XB+6, close);break;case 1:Set_Servo_Pulse(XB+0, close);Set_Servo_Pulse(XB+1, open);Set_Servo_Pulse(XB+2, open);Set_Servo_Pulse(XB+3, close);Set_Servo_Pulse(XB+4, close1);Set_Servo_Pulse(XB+5, close1);Set_Servo_Pulse(XB+6, close);break;case 2:Set_Servo_Pulse(XB+0, open);Set_Servo_Pulse(XB+1, open);Set_Servo_Pulse(XB+2, close);Set_Servo_Pulse(XB+3, open);Set_Servo_Pulse(XB+4, open);Set_Servo_Pulse(XB+5, close1);Set_Servo_Pulse(XB+6, open);break;case 3:Set_Servo_Pulse(XB+0, open);Set_Servo_Pulse(XB+1, open);Set_Servo_Pulse(XB+2, open);Set_Servo_Pulse(XB+3, open);Set_Servo_Pulse(XB+4, close1);Set_Servo_Pulse(XB+5, close1);Set_Servo_Pulse(XB+6, open);break;case 4:Set_Servo_Pulse(XB+0, close);Set_Servo_Pulse(XB+1, open);Set_Servo_Pulse(XB+2, open);Set_Servo_Pulse(XB+3, close);Set_Servo_Pulse(XB+4, close1);Set_Servo_Pulse(XB+5, open);Set_Servo_Pulse(XB+6, open);break;case 5:Set_Servo_Pulse(XB+0, open);Set_Servo_Pulse(XB+1, close);Set_Servo_Pulse(XB+2, open);Set_Servo_Pulse(XB+3, open);Set_Servo_Pulse(XB+4, close1);Set_Servo_Pulse(XB+5, open);Set_Servo_Pulse(XB+6, open);break;case 6:Set_Servo_Pulse(XB+0, open);Set_Servo_Pulse(XB+1, close);Set_Servo_Pulse(XB+2, open);Set_Servo_Pulse(XB+3, open);Set_Servo_Pulse(XB+4, open);Set_Servo_Pulse(XB+5, open);Set_Servo_Pulse(XB+6, open);break;case 7:Set_Servo_Pulse(XB+0, open);Set_Servo_Pulse(XB+1, open);Set_Servo_Pulse(XB+2, open);Set_Servo_Pulse(XB+3, close);Set_Servo_Pulse(XB+4, close1);Set_Servo_Pulse(XB+5, close1);Set_Servo_Pulse(XB+6, close);break;case 8:Set_Servo_Pulse(XB+0, open);Set_Servo_Pulse(XB+1, open);Set_Servo_Pulse(XB+2, open);Set_Servo_Pulse(XB+3, open);Set_Servo_Pulse(XB+4, open);Set_Servo_Pulse(XB+5, open);Set_Servo_Pulse(XB+6, open);break;case 9:Set_Servo_Pulse(XB+0, open);Set_Servo_Pulse(XB+1, open);Set_Servo_Pulse(XB+2, open);Set_Servo_Pulse(XB+3, open);Set_Servo_Pulse(XB+4, close1);Set_Servo_Pulse(XB+5, open);Set_Servo_Pulse(XB+6, open);break;	default:Set_Servo_Pulse(XB+0, close);Set_Servo_Pulse(XB+1, close);Set_Servo_Pulse(XB+2, close);Set_Servo_Pulse(XB+3, close);Set_Servo_Pulse(XB+4, close1);Set_Servo_Pulse(XB+5, close1);Set_Servo_Pulse(XB+6, close);break;		}XB=1*7;switch (time_min[0]){case 0:Set_Servo_Pulse(XB+0, open);Set_Servo_Pulse(XB+1, open);Set_Servo_Pulse(XB+2, open);Set_Servo_Pulse(XB+3, open);Set_Servo_Pulse(XB+4, open);Set_Servo_Pulse(XB+5, open);Set_Servo_Pulse(XB+6, close);break;case 1:Set_Servo_Pulse(XB+0, close);Set_Servo_Pulse(XB+1, open);Set_Servo_Pulse(XB+2, open);Set_Servo_Pulse(XB+3, close);Set_Servo_Pulse(XB+4, close1);Set_Servo_Pulse(XB+5, close1);Set_Servo_Pulse(XB+6, close);break;case 2:Set_Servo_Pulse(XB+0, open);Set_Servo_Pulse(XB+1, open);Set_Servo_Pulse(XB+2, close);Set_Servo_Pulse(XB+3, open);Set_Servo_Pulse(XB+4, open);Set_Servo_Pulse(XB+5, close1);Set_Servo_Pulse(XB+6, open);break;case 3:Set_Servo_Pulse(XB+0, open);Set_Servo_Pulse(XB+1, open);Set_Servo_Pulse(XB+2, open);Set_Servo_Pulse(XB+3, open);Set_Servo_Pulse(XB+4, close1);Set_Servo_Pulse(XB+5, close1);Set_Servo_Pulse(XB+6, open);break;case 4:Set_Servo_Pulse(XB+0, close);Set_Servo_Pulse(XB+1, open);Set_Servo_Pulse(XB+2, open);Set_Servo_Pulse(XB+3, close);Set_Servo_Pulse(XB+4, close1);Set_Servo_Pulse(XB+5, open);Set_Servo_Pulse(XB+6, open);break;case 5:Set_Servo_Pulse(XB+0, open);Set_Servo_Pulse(XB+1, close);Set_Servo_Pulse(XB+2, open);Set_Servo_Pulse(XB+3, open);Set_Servo_Pulse(XB+4, close1);Set_Servo_Pulse(XB+5, open);Set_Servo_Pulse(XB+6, open);break;case 6:Set_Servo_Pulse(XB+0, open);Set_Servo_Pulse(XB+1, close);Set_Servo_Pulse(XB+2, open);Set_Servo_Pulse(XB+3, open);Set_Servo_Pulse(XB+4, open);Set_Servo_Pulse(XB+5, open);Set_Servo_Pulse(XB+6, open);break;case 7:Set_Servo_Pulse(XB+0, open);Set_Servo_Pulse(XB+1, open);Set_Servo_Pulse(XB+2, open);Set_Servo_Pulse(XB+3, close);Set_Servo_Pulse(XB+4, close1);Set_Servo_Pulse(XB+5, close1);Set_Servo_Pulse(XB+6, close);break;case 8:Set_Servo_Pulse(XB+0, open);Set_Servo_Pulse(XB+1, open);Set_Servo_Pulse(XB+2, open);Set_Servo_Pulse(XB+3, open);Set_Servo_Pulse(XB+4, open);Set_Servo_Pulse(XB+5, open);Set_Servo_Pulse(XB+6, open);break;case 9:Set_Servo_Pulse(XB+0, open);Set_Servo_Pulse(XB+1, open);Set_Servo_Pulse(XB+2, open);Set_Servo_Pulse(XB+3, open);Set_Servo_Pulse(XB+4, close1);Set_Servo_Pulse(XB+5, open);Set_Servo_Pulse(XB+6, open);break;	default:Set_Servo_Pulse(XB+0, close);Set_Servo_Pulse(XB+1, close);Set_Servo_Pulse(XB+2, close);Set_Servo_Pulse(XB+3, close);Set_Servo_Pulse(XB+4, close1);Set_Servo_Pulse(XB+5, close1);Set_Servo_Pulse(XB+6, close);break;	}	XB=2*7;switch (time_hour[1]){case 0:Set_Servo_Pulse(XB+0, open);Set_Servo_Pulse(XB+1, open);Set_Servo_Pulse(XB+2, open);Set_Servo_Pulse(XB+3, open);Set_Servo_Pulse(XB+4, open);Set_Servo_Pulse(XB+5, open);Set_Servo_Pulse(XB+6, close);break;case 1:Set_Servo_Pulse(XB+0, close);Set_Servo_Pulse(XB+1, open);Set_Servo_Pulse(XB+2, open);Set_Servo_Pulse(XB+3, close);Set_Servo_Pulse(XB+4, close1);Set_Servo_Pulse(XB+5, close1);Set_Servo_Pulse(XB+6, close);break;case 2:Set_Servo_Pulse(XB+0, open);Set_Servo_Pulse(XB+1, open);Set_Servo_Pulse(XB+2, close);Set_Servo_Pulse(XB+3, open);Set_Servo_Pulse(XB+4, open);Set_Servo_Pulse(XB+5, close1);Set_Servo_Pulse(XB+6, open);break;case 3:Set_Servo_Pulse(XB+0, open);Set_Servo_Pulse(XB+1, open);Set_Servo_Pulse(XB+2, open);Set_Servo_Pulse(XB+3, open);Set_Servo_Pulse(XB+4, close1);Set_Servo_Pulse(XB+5, close1);Set_Servo_Pulse(XB+6, open);break;case 4:Set_Servo_Pulse(XB+0, close);Set_Servo_Pulse(XB+1, open);Set_Servo_Pulse(XB+2, open);Set_Servo_Pulse(XB+3, close);Set_Servo_Pulse(XB+4, close1);Set_Servo_Pulse(XB+5, open);Set_Servo_Pulse(XB+6, open);break;case 5:Set_Servo_Pulse(XB+0, open);Set_Servo_Pulse(XB+1, close);Set_Servo_Pulse(XB+2, open);Set_Servo_Pulse(XB+3, open);Set_Servo_Pulse(XB+4, close1);Set_Servo_Pulse(XB+5, open);Set_Servo_Pulse(XB+6, open);break;case 6:Set_Servo_Pulse(XB+0, open);Set_Servo_Pulse(XB+1, close);Set_Servo_Pulse(XB+2, open);Set_Servo_Pulse(XB+3, open);Set_Servo_Pulse(XB+4, open);Set_Servo_Pulse(XB+5, open);Set_Servo_Pulse(XB+6, open);break;case 7:Set_Servo_Pulse(XB+0, open);Set_Servo_Pulse(XB+1, open);Set_Servo_Pulse(XB+2, open);Set_Servo_Pulse(XB+3, close);Set_Servo_Pulse(XB+4, close1);Set_Servo_Pulse(XB+5, close1);Set_Servo_Pulse(XB+6, close);break;case 8:Set_Servo_Pulse(XB+0, open);Set_Servo_Pulse(XB+1, open);Set_Servo_Pulse(XB+2, open);Set_Servo_Pulse(XB+3, open);Set_Servo_Pulse(XB+4, open);Set_Servo_Pulse(XB+5, open);Set_Servo_Pulse(XB+6, open);break;case 9:Set_Servo_Pulse(XB+0, open);Set_Servo_Pulse(XB+1, open);Set_Servo_Pulse(XB+2, open);Set_Servo_Pulse(XB+3, open);Set_Servo_Pulse(XB+4, close1);Set_Servo_Pulse(XB+5, open);Set_Servo_Pulse(XB+6, open);break;	default:Set_Servo_Pulse(XB+0, close);Set_Servo_Pulse(XB+1, close);Set_Servo_Pulse(XB+2, close);Set_Servo_Pulse(XB+3, close);Set_Servo_Pulse(XB+4, close1);Set_Servo_Pulse(XB+5, close1);Set_Servo_Pulse(XB+6, close);break;	}	XB=3*7;switch (time_hour[0]){case 0:Set_Servo_Pulse(XB+0, close);Set_Servo_Pulse(XB+1, close);//Set_Servo_Pulse(XB+2, open);Set_Servo_Pulse(XB+3, open);Set_Servo_Pulse(XB+4, open);Set_Servo_Pulse(XB+5, open);Set_Servo_Pulse(XB+6, close);break;case 1:Set_Servo_Pulse(XB+0, open);Set_Servo_Pulse(XB+1, open);//Set_Servo_Pulse(XB+2, open);Set_Servo_Pulse(XB+3, close);Set_Servo_Pulse(XB+4, close1);Set_Servo_Pulse(XB+5, close1);Set_Servo_Pulse(XB+6, close);break;default:Set_Servo_Pulse(XB+0, close);Set_Servo_Pulse(XB+1, close);//Set_Servo_Pulse(XB+2, close);Set_Servo_Pulse(XB+3, close);Set_Servo_Pulse(XB+4, close1);Set_Servo_Pulse(XB+5, close1);Set_Servo_Pulse(XB+6, close);break;}}}break;default:break;}	}
}

 main.h

#ifndef __main_H
#define __main_H
#include "stm32f1xx.h"
#include "stm32f1xx_hal.h"
#include "stm32f1xx_it.h"
#include "stdio.h"
//#include "stdarg.h"
#include "string.h"
#include "delay.h"
#include "sys.h"
#include "led.h"
//#include "key.h"
//#include "exti.h"
#include "time.h"
//#include "pwm.h"
//#include "ppm.h"
#include "usart.h"
//#include "adc.h"
//#include "24cxx.h"
//#include "spi.h"
//#include "nrf24l01.h"#endif

 usart.c

#include "main.h"
#include "usart.h"uint8_t g_usart_rx_buf[USART_REC_LEN];
uint16_t g_usart_rx_sta = 0;
uint16_t g_usart1_rx_flag = 0;
uint8_t g_rx_buffer[RXBUFFERSIZE];  /* HAL库使用的串口接收缓冲 */
UART_HandleTypeDef g_uart1_handle;  /* UART句柄 *//*串口X初始化函数*/
void usart_init(uint32_t BaudRate)
{/*UART 初始化设置*/g_uart1_handle.Instance = USART1;                                       /* USART_UX */g_uart1_handle.Init.BaudRate = BaudRate;                                  /* 波特率 */g_uart1_handle.Init.WordLength = UART_WORDLENGTH_8B;                      /* 字长为8位数据格式 */g_uart1_handle.Init.StopBits = UART_STOPBITS_1;                           /* 一个停止位 */g_uart1_handle.Init.Parity = UART_PARITY_NONE;                            /* 无奇偶校验位 */g_uart1_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE;                      /* 无硬件流控 */g_uart1_handle.Init.Mode = UART_MODE_TX_RX;                               /* 收发模式 */HAL_UART_Init(&g_uart1_handle);                                           /* HAL_UART_Init()会使能UART1 *//* 该函数会开启接收中断:标志位UART_IT_RXNE,并且设置接收缓冲以及接收缓冲接收最大数据量 */HAL_UART_Receive_IT(&g_uart1_handle, (uint8_t *)g_rx_buffer, 1); 
}/*usart初始化函数*/
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{GPIO_InitTypeDef gpio_init_struct;if (huart->Instance == USART1)                            /* 如果是串口1,进行串口1 MSP初始化 */{__HAL_RCC_GPIOA_CLK_ENABLE();                             /* 使能串口TX\RX脚时钟 */__HAL_RCC_USART1_CLK_ENABLE();                                  /* 使能串口时钟 */gpio_init_struct.Pin = GPIO_PIN_9;               /* 串口发送引脚号 */gpio_init_struct.Mode = GPIO_MODE_AF_PP;                /* 复用推挽输出 */gpio_init_struct.Pull = GPIO_PULLUP;                    /* 上拉 */gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;          /* IO速度设置为高速 */HAL_GPIO_Init(GPIOA, &gpio_init_struct);gpio_init_struct.Pin = GPIO_PIN_10;               /* 串口RX脚 模式设置 */gpio_init_struct.Mode = GPIO_MODE_AF_INPUT;    HAL_GPIO_Init(GPIOA, &gpio_init_struct);   /* 串口RX脚 必须设置成输入模式 */#if USART_EN_RXHAL_NVIC_EnableIRQ(USART1_IRQn);                      /* 使能USART1中断通道 */HAL_NVIC_SetPriority(USART1_IRQn, 3, 3);              /* 组2,最低优先级:抢占优先级3,子优先级3 */
#endif}
}
uint8_t time_hour[2],time_min[2],time_second[2];
char * recive_s;
char * recive_s1;
//char string_recive1[] = "WIFI CONNECTED\r\nWIFI GOT IP";
char string_recive1[] = "WIFI CONNECTED";
//char string_recive2[39] = "AT+CIPSNTPCFG=1,8,\"ntp1.aliyun.com\"\r\nOK";
char string_recive2[] = "AT+CIPSNTPCFG=1,8,";
//char string_recive22[41] = "AT+CIPSNTPCFG=1,8,\"ntp1.aliyun.com\"\r\n\r\nOK";
char string_recive3[] = "AT+CIPSNTPTIME";
/*串口数据接收回调函数*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{if (huart->Instance == USART1)                    /* 如果是串口1 */{     recive_s = strstr((char*)g_rx_buffer,string_recive1);if (recive_s!=NULL){g_usart1_rx_flag = 20;}recive_s = strstr((char*)g_rx_buffer,string_recive2);if ((recive_s!=NULL)&&((*(recive_s+39)==0X4F)&&(*(recive_s+40)==0X4B))) {g_usart1_rx_flag = 10;}recive_s = strstr((char*)g_rx_buffer,string_recive3);if (/*61字符*/ ((recive_s!=NULL)&&((*(recive_s+57)==0X4F)&&(*(recive_s+58)==0X4B)))||/*60字符*/ ((recive_s!=NULL)&&((*(recive_s+56)==0X4F)&&(*(recive_s+57)==0X4B)))){if( ((*(recive_s+50))==0x31)&& ((*(recive_s+51))==0x39)&& ((*(recive_s+52))==0x37)&& ((*(recive_s+53))==0x30)		//1970年---获取时间失败){g_usart1_rx_flag = 0;}else{if(				//必须是有效数字((*(recive_s+50))>=0x30) && ((*(recive_s+50))<=0x39) && ((*(recive_s+51))>=0x30) && ((*(recive_s+51))<=0x39) && ((*(recive_s+52))>=0x30) && ((*(recive_s+52))<=0x39) && ((*(recive_s+53))>=0x30) && ((*(recive_s+53))<=0x39) )g_usart1_rx_flag = 1;//							if(((*(recive_s+41))-0x30)*10+((*(recive_s+42))-0x30)>=12)
//							{		
//								time_hour[0]=((((*(recive_s+41))-0x30)*10+((*(recive_s+42))-0x30))-12)/10;
//								time_hour[1]=((((*(recive_s+41))-0x30)*10+((*(recive_s+42))-0x30))-12)%10;
//							}else{
//								time_hour[0]=(*(recive_s+41))-0x30;
//								time_hour[1]=(*(recive_s+42))-0x30;
//							}if(((*(recive_s+41))-0x30)*10+((*(recive_s+42))-0x30)>=20)//因为小时的首位只有一个1,因此大于20点默认回归到12小时制{		time_hour[0]=((((*(recive_s+41))-0x30)*10+((*(recive_s+42))-0x30))-12)/10;time_hour[1]=((((*(recive_s+41))-0x30)*10+((*(recive_s+42))-0x30))-12)%10;}else{time_hour[0]=((((*(recive_s+41))-0x30)*10+((*(recive_s+42))-0x30)))/10;time_hour[1]=((((*(recive_s+41))-0x30)*10+((*(recive_s+42))-0x30)))%10;}TIME_HOUR_24h = ((*(recive_s+41))-0x30)*10+((*(recive_s+42))-0x30);time_min[0]=(*(recive_s+44))-0x30;time_min[1]=(*(recive_s+45))-0x30;							time_second[0]=(*(recive_s+47))-0x30;time_second[1]=(*(recive_s+48))-0x30;//							time_hour[0]=(*(recive_s+44))-0x30;
//							time_hour[1]=(*(recive_s+45))-0x30;							
//							time_min[0]=(*(recive_s+47))-0x30;
//							time_min[1]=(*(recive_s+48))-0x30;}}
//			//60个字符
//			if ((recive_s!=NULL)&&((*(recive_s+56)==0X4F)&&(*(recive_s+57)==0X4B)))
//			{
//				
//				if( 
//								((*(recive_s+50))==0x31)&& ((*(recive_s+51))==0x39)&& ((*(recive_s+52))==0x37)&& ((*(recive_s+53))==0x30)		//1970年---获取时间失败
//								)
//						{
//							g_usart1_rx_flag = 0;
//						}else{
//							if(				//必须是有效数字
//									 ((*(recive_s+50))>=0x30) && ((*(recive_s+50))<=0x39) 
//								&& ((*(recive_s+51))>=0x30) && ((*(recive_s+51))<=0x39) 
//								&& ((*(recive_s+52))>=0x30) && ((*(recive_s+52))<=0x39) 
//								&& ((*(recive_s+53))>=0x30) && ((*(recive_s+53))<=0x39) 
//							)
//							g_usart1_rx_flag = 1;
//							
//							if(((*(recive_s+41))-0x30)*10+((*(recive_s+42))-0x30)>=12)
//							{				
//								time_hour[0]=0;
//								time_hour[1]=(((*(recive_s+41))-0x30)*10+((*(recive_s+42))-0x30))-12;
//							}else{
//								time_hour[0]=(*(recive_s+41))-0x30;
//								time_hour[1]=(*(recive_s+42))-0x30;
//							}
//							time_min[0]=(*(recive_s+44))-0x30;
//							time_min[1]=(*(recive_s+45))-0x30;							
//							time_second[0]=(*(recive_s+47))-0x30;
//							time_second[1]=(*(recive_s+48))-0x30;
//							
//						}
//			}}
}void USART1_IRQHandler(void)
{HAL_UART_IRQHandler(&g_uart1_handle);   /* 调用HAL库中断处理公用函数 */HAL_UART_Receive_IT(&g_uart1_handle, (uint8_t *)g_rx_buffer, RXBUFFERSIZE);} /* 加入以下代码, 支持printf函数, 而不需要选择use MicroLIB */#if 1#if (__ARMCC_VERSION >= 6010050)            /* 使用AC6编译器时 */
__asm(".global __use_no_semihosting\n\t");  /* 声明不使用半主机模式 */
__asm(".global __ARM_use_no_argv \n\t");    /* AC6下需要声明main函数为无参数格式,否则部分例程可能出现半主机模式 */#else
/* 使用AC5编译器时, 要在这里定义__FILE 和 不使用半主机模式 */
#pragma import(__use_no_semihosting)struct __FILE
{int handle;/* Whatever you require here. If the only file you are using is *//* standard output using printf() for debugging, no file handling *//* is required. */
};#endif/* 不使用半主机模式,至少需要重定义_ttywrch\_sys_exit\_sys_command_string函数,以同时兼容AC6和AC5模式 */
int _ttywrch(int ch)
{ch = ch;return ch;
}/* 定义_sys_exit()以避免使用半主机模式 */
void _sys_exit(int x)
{x = x;
}char *_sys_command_string(char *cmd, int len)
{return NULL;
}/* FILE 在 stdio.h里面定义. */
FILE __stdout;/* MDK下需要重定义fputc函数, printf函数最终会通过调用fputc输出字符串到串口 */
int fputc(int ch, FILE *f)
{while ((USART1->SR & 0X40) == 0);     /* 等待上一个字符发送完成 */USART1->DR = (uint8_t)ch;             /* 将要发送的字符 ch 写入到DR寄存器 */return ch;
}
#endif

 usart.h

#ifndef __USART_H
#define __USART_H#define USART_REC_LEN               200         /* 定义最大接收字节数 200 */
#define USART_EN_RX                 1           /* 使能(1)/禁止(0)串口1接收 */
#define RXBUFFERSIZE   100                        /* 缓存大小 */extern UART_HandleTypeDef g_uart1_handle;       /* HAL UART句柄 */
extern uint8_t  g_usart_rx_buf[USART_REC_LEN];  /* 接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 */
extern uint16_t g_usart_rx_sta;                 /* 接收状态标记 */
extern uint8_t g_rx_buffer[RXBUFFERSIZE];       /* HAL库USART接收Buffer */
extern uint16_t g_usart1_rx_flag ;              /*数据接收标志*/      extern uint8_t time_hour[2],time_min[2],time_second[2];void usart_init(uint32_t BaudRate);                /* 串口初始化函数 */extern uint16_t g_usart1_rx_flag;
extern uint8_t TIME_HOUR_24h;
#endif

time.c

#include "main.h"TIM_HandleTypeDef g_timx_handle;  /* 定时器句柄 */void time_init(void)
{g_timx_handle.Instance = TIM2;                        /* 通用定时器4 */g_timx_handle.Init.Prescaler = 72-1;                /* 设置预分频系数 */g_timx_handle.Init.CounterMode = TIM_COUNTERMODE_UP;  /* 递增计数模式 */g_timx_handle.Init.Period = TIMER_TICK;                   /* 自动装载值 */HAL_TIM_Base_Init(&g_timx_handle);HAL_TIM_Base_Start_IT(&g_timx_handle);         /* 使能定时器x及其更新中断 */
}void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
{if (htim->Instance == TIM2){__HAL_RCC_TIM2_CLK_ENABLE();            /* 使能TIM时钟 */HAL_NVIC_SetPriority(TIM2_IRQn, 1, 3); /* 抢占1,子优先级3,组2 */HAL_NVIC_EnableIRQ(TIM2_IRQn);         /* 开启ITM3中断 */}
}
uint16_t tim_cnt;
void TIM2_IRQHandler(void)
{HAL_TIM_IRQHandler(&g_timx_handle); /* 定时器中断公共处理函数 */
}Servo_Ctrl servo[SERVO_NUM];  // 舵机控制数组void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) /*定时器更新中断回调函数*/
{static uint16_t global_counter = 0;if (htim->Instance == TIM2){
//			ADC_PPM();if(tim_cnt>=g_usart1_rx_flag*500){tim_cnt = 0;LED0_TOGGLE();}else{tim_cnt++;}//pwm生成for(uint8_t i=0; i<SERVO_NUM; i++) {if(global_counter == 0) {  // 新周期开始时拉高所有引脚//        GPIO_SetBits(servo[i].GPIOx, servo[i].GPIO_Pin);HAL_GPIO_WritePin(servo[i].GPIOx,servo[i].GPIO_Pin , GPIO_PIN_SET);servo[i].counter = 0;} else {servo[i].counter += TIMER_TICK;if(servo[i].counter >= servo[i].pulse_us) {  // 达到脉宽时间后拉低//          GPIO_ResetBits(servo[i].GPIOx, servo[i].GPIO_Pin);HAL_GPIO_WritePin(servo[i].GPIOx,servo[i].GPIO_Pin , GPIO_PIN_RESET);}}}global_counter += TIMER_TICK;if(global_counter >= PWM_PERIOD) {global_counter = 0;  // 周期复位}}
}

 time.h

#ifndef __TIME_H
#define __TIME_H#include "main.h"#define SERVO_NUM  23   // 舵机数量
#define PWM_PERIOD  20000 // 20ms周期(单位:us)
#define TIMER_TICK  100    // 定时器中断间隔(单位:us)// 舵机控制结构体
typedef struct {GPIO_TypeDef* GPIOx;  // GPIO端口uint16_t GPIO_Pin;    // GPIO引脚uint16_t pulse_us;    // 当前脉宽(单位:us)uint16_t counter;     // 内部计时器
} Servo_Ctrl;extern Servo_Ctrl servo[SERVO_NUM];  // 舵机控制数组void time_init(void);
#endif

2.esp8266链接网络时间采用NTP时间为基准;

链接wifi:

AT+CWJAP="xxxxxx","*************"

链接NTP:

AT+CIPSNTPCFG=1,8,"ntp1.aliyun.com"

发送时间请求:

AT+CIPSNTPTIME?

3.舵轮时钟图纸:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/87850.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/87850.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Redis的单线程和多线程(单Worker线程)

Redis的单线程和多线程 Redis6.0之前是单线程的&#xff0c;6.0之后是多线程的&#xff0c;我们先了解6.0版本之前的单线程Redis。但其实无论6.0之前还是6.0之后&#xff0c;redis用于工作的线程也只有一个&#xff0c;所以也可以说redis一直是单线程的。 Redis单线程 Redis 6.…

OSPFv3基础

文章目录 OSPFv3基础OSPFv3的改进OSPFv2 v3相同OSPFv2 v3不同 &#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f916;Datacom专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2025年07月07日22点31分 OSPFv3基础 OSPFv3协议号依然为89&#xff0c;在I…

前端篇——HTML知识点体系

目录 一、基础结构与文本 1. 文档基础 2. 文本元素 二、多媒体元素 1. 图像 2. 音频 3. 视频 三、列表系统 1. 无序列表 2. 有序列表 3. 定义列表 四、表格系统 1. 表格结构 2. 合并单元格 五、表单系统 1. 输入控件 2. 表单元素 3. 高级表单特性 六、布局系…

产品需求管理文档中,需求模块是怎么界定的

产品需求文档中&#xff0c;需求模块的界定方式主要包括&#xff1a;1、基于业务流程的功能划分、2、按用户角色使用场景分类、3、根据系统架构与技术边界拆解、4、对数据实体和功能点进行组合聚类、5、结合未来演进节奏设置独立迭代单元。 其中&#xff0c;“基于业务流程的功…

国内免代理免费使用Gemini大模型实战

文章目录 一、免费申请Gemini API密钥二、使用openai-gemini1、在github上找到openai-gemini2、将openai-gemini部署到Netlify3、在Cherry Studio中配置和使用gemini的模型1&#xff09;在Cherry Studio中配置gemini API2&#xff09;在Cherry Studio中使用gemini 的模型 4、在…

day46-tomcat-java业务部署

1. ✅选型1.1. &#x1f3af;中间件java web中间件说明tomcat组件&#xff0c;功能多jetty精简&#xff0c;功能少一些......weblogic使用oracle数据库配合weblogic(商业)国产&#xff1a;东方通(TongWEB)1.2. &#x1f4cc;jdkjdk选型说明jdk(oracle jdk)商业版&#xff0c;jd…

[netty5: HttpServerCodec HttpClientCodec]-源码分析

在阅读该篇文章之前&#xff0c;推荐先阅读以下内容&#xff1a; [netty5: ChannelHandler & ChannelHandlerAdapter]-源码解析[netty5: HttpObjectEncoder & HttpObjectDecoder]-源码解析 HttpServerCodec HttpServerCodec 是一个 Netty 编解码器&#xff0c;结合 …

华为OD机试 2025B卷 - 数组组成的最小数字(C++PythonJAVAJSC语言)

2025B卷目录点击查看: 华为OD机试2025B卷真题题库目录|机考题库 + 算法考点详解 2025B卷 100分题型 最新华为OD机试 真题目录:点击查看目录 华为OD面试真题精选:点击立即查看 2025华为od 机试2025B卷-华为机考OD2025年B卷 题目描述 给定一个整型数组,请从该数组中选…

Ubuntu下Tomcat的配置

进入Tomcat的conf目录下 1 备份配置文件 cp server.xml server.xml.2下载server.xml&#xff0c;用notepad文本编辑器打开 2 修改Tomcat的端口号 找到如下内容<Connector port"8080" protocol"HTTP/1.1"connectionTimeout"20000"redirectPort…

Docker部Ollama安装、本地大模型配置与One-API接入

Docker 安装 Ollama Ollama 支持 Docker 安装,极大简化了部署流程。以下是具体步骤: 创建ollama文件夹 创建 docker-compose.yaml 文件新建一个 docker-compose.yaml 文件,内容如下: 编辑文件 …

ABB焊接机器人智能节气仪

在现代焊接工业中&#xff0c;ABB焊接机器人凭借其高精度、高效率等优势被广泛应用。而在焊接过程中&#xff0c;节气是一个重要的考量因素&#xff0c;这就凸显出ABB焊接机器人智能节气仪的重要性。ABB焊接机器人节气是提高焊接生产效益的关键环节。传统的焊接过程中&#xff…

摄影后期:使用Photoshop进行暗角控制

方法一&#xff1a;ctrlshiftR调出镜头校正工具&#xff0c;调整晕影 方法二&#xff1a;

pyhton基础【24】面向对象进阶五

目录 十五.多继承的继承顺序 - mro 调用父类方式不同导致结果不同 单继承中的super 简单总结 面试题 十六.魔术方法 魔术方法概述 魔术方法概览 __getattribute__属性 __getattribute__注意事项 常用的魔术方法 __doc__ __module__和__class__ __init__ __del__…

如何保障MySQL客户端连接数据库安全更安全

公司员工或外协人员&#xff0c;直接使用业务账号或高权限账号连接MySQL服务器&#xff0c;如同让数据在连接时减少风险——账号密码易泄露、操作行为难追溯、安全风险陡增&#xff01;尤其是在客户端连接环节&#xff0c;如何确保每一个接入点都安全可控&#xff0c;每一次操作…

机器学习入门:线性回归详解及Scikit-learn API使用指南

一、线性回归概述线性回归是统计学和机器学习领域中最基础、最广泛应用的预测建模技术之一。自19世纪初由弗朗西斯高尔顿(Francis Galton)首次提出以来&#xff0c;线性回归已成为数据分析的核心工具&#xff0c;在经济学、社会科学、生物统计学、工程学等众多领域发挥着重要作…

高斯牛顿法求解三维变换矩阵的数学推导

目录一、问题定义二、李代数基础三、雅可比矩阵推导四、高斯牛顿迭代1. 整体雅可比矩阵2. 正规方程构建3. 参数更新4. 李代数更新五、理论优势分析一、问题定义 给定两组三维点云&#xff1a;源点云 P{pi∈R3}i1NP \{p_i \in \mathbb{R}^3\}_{i1}^NP{pi​∈R3}i1N​&#xff0…

JAVA 商城系统为什么受欢迎?ZKmall开源商城灵活定制 + 插件接入适配市场

在电商系统开发这块&#xff0c;技术选得好不好&#xff0c;直接关系到平台稳不稳定、能不能扩展、适配能力强不强。JAVA 语言因为 “跨平台性突出、安全性高、可扩展性好” 这些特点&#xff0c;成了企业级电商系统的首选技术。而 ZKmall 商城基于 JAVA 开发的商城系统&#x…

【数据结构之哈夫曼树与编码实现】

文章目录 前言一、哈夫曼树与哈夫曼编码简介1. 什么是哈夫曼树&#xff1f;2. 为什么需要哈夫曼编码&#xff1f; 二、哈夫曼编码原理三、哈夫曼树的构建步骤详解1. 统计字符频率2. 定义哈夫曼树节点3. 最小堆&#xff08;优先队列&#xff09;的构造4. 合并节点&#xff0c;构…

基于Hadoop的京东厨具商品数据分析及商品价格预测系统的设计与实现

文章目录有需要本项目的代码或文档以及全部资源&#xff0c;或者部署调试可以私信博主项目介绍数据采集用户界面系统展示管理员界面每文一语有需要本项目的代码或文档以及全部资源&#xff0c;或者部署调试可以私信博主 项目介绍 本项目围绕“京东厨具数据分析系统的设计与实…

深入解析TCP:可靠传输的核心机制与实现逻辑(三次握手、四次挥手、流量控制、滑动窗口、拥塞控制、慢启动、延时应答、面向字节流、粘包问题)

Linux系列 文章目录 Linux系列一、TCP连接的建立与断开1.1 TCP 三次握手1.2 TCP四次挥手1. TCP连接的本质是应用层间的通信通道2. 断开连接的核心是终止应用层通信3. 常见误解澄清 二、TCP协议的机制2.1 流量控制2.2 滑动窗口2.2.1 滑动窗口的工作原理2.2.2 基于滑动窗口快重传…