完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
扫一扫,分享给好友
|
|
相关推荐
1个回答
|
|
宠物喂食器的设计-基于涂鸦三明治三件套
本文章允许涂鸦智能转载使用 去年疫情突发,全国很多地区封城,封小区,让原本备受宠爱的主子与铲屎官异地分离。遇到有准备的铲屎官,主子们还能勉强度日,那些没有准备的主子只能靠吃猫砂,吃垃圾度日,甚至有些小可怜被活活饿死。 疫情缓解后,为了避免这样的事件再次发生,也为了解放懒惰的铲屎官,于是自动猫砂盆,自动喂食器,自动喂水器的需求不断提升。有数据显示,疫情后自动猫砂盆增长879%,自动喂水器增长120%,自动喂食器增长也超一倍。毕竟主子是家里的老大,要吃好喝好还要拉好。 此次DIY自动投食器由涂鸦智能开展的【宠物喂食器】实战营策划,并提供了涂鸦三明治开发套件,其中包括: 涂鸦三明治 Wi-Fi MCU 通信板1 涂鸦三明治H桥直流电机驱动功能板1 涂鸦三明治直流供电电源板*1。 除此之外,用户还需要自行准备MCU控制板和电机等组件,该WiFi模组出厂默认为透传模式,只负责数据转发,不负责数据处理,所以我们只需要准备MCU用于数据处理和外设控制。 涂鸦智能平台 1.前往涂鸦智能开发平台 (https://auth.tuya.com/register_source=7b811ac2e872ccb62376ba4dfe0568eb)注册开发者账号 2.在涂鸦loT平台创建产品 3.在小家电品类里面找到【宠物喂食器】 4.使用MCU SDK方案,完善产品信息 5.产品创建后添加标准功能 6.硬件开发选项 以上步骤更加具体配置可参考涂鸦IOT平台产品创建流程(https://shimo.im/docs/HvHRgTtjUDYIvLlA/read)产品创建完成后下载开发资料,建议全部下载,其中MCU SDK的内容会根据你所选择的标准功能不同而不同,为了方便可在选择功能时尽可能多的考虑到需要配置的功能,当然,即使你一个不选,SDK也开放了各个功能的函数,只是被屏蔽,可自行放开。 功能调试 MCU对接方案通信原理图 1.WIFI模组调试 打开上一步最终下载的文件如图,接着我们打开涂鸦调试助手 将WiFi的通信板的串口1接到u***-ttl上,接到电脑,一定是串口1,串口0是查看模组本身的logo的,打开涂鸦调试助手。选择MCU模拟,此时调试助手就相当于是MCU,可以与WiFi模组通信,可用此来调试WiFi模组。选择好串口,波特率默认9600.功能点调试文件选择之前下载的json文件。初始化配置保持默认,点击开始调试。如收到以下数据说明模组与助手连接正常,可以开始调试。 此时我们下载涂鸦智能APP,注册后选择添加设备,在小家电里面找到宠物喂食器,选择2.4G的WiFi网络。输入密码。点击下一步 此时在模组调试助手点击smart配网,手机点击下一步 配网成功后会在手机APP和调试助手同时看到相应信息。连接成功后会定时发送心跳包保持连接。 至此WiFi模组配网完成,改配网信息会保存在WiFi模组内部,下次上电会自动连接该网络。如果更换网络环境需要重置后再次配网。此时可在DP CMD里面测试相关DP点的数据上报,观察有无数据的上报下发。 2.MCU调试 WiFi模组调试完成之后我们需要调试我们的主控,也就是MCU,在我这里就是STM32F103ZET6。在进行MCU调试之前我们需要先进行SDK的移植,将之前下载的SDK移植到我们的STM32项目中。 1.工程搭建 本文实在串口驱动实验的基础上搭建的,因为后面需要用到串口; usart.h #ifndef __USART_H #define __USART_H #include "stdio.h" #include "sys.h" #define USART_REC_LEN 200 //定义最大接收字节数 200 #define EN_USART1_RX 1 //使能(1)/禁止(0)串口1接收 extern u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 extern u16 USART_RX_STA; //接收状态标记 //如果想串口中断接收,请不要注释以下宏定义 void uart_init(u32 bound); void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch); #endif usart.c #include "sys.h" #include "usart.h" #include "mcu_api.h" #include "protocol.h" #include "system.h" #include "wifi.h" // //如果使用ucos,则包括下面的头文件即可. #if SYSTEM_SUPPORT_OS #include "includes.h" //ucos 使用 #endif #if 1 #pragma import(__use_no_semihosting) //标准库需要的支持函数 struct __FILE { int handle; }; FILE __stdout; //定义_sys_exit()以避免使用半主机模式 void _sys_exit(int x) { x = x; } //重定义fputc函数 int fputc(int ch, FILE *f) { while((USART1->SR&0X40)==0);//循环发送,直到发送完毕 USART1->DR = (u8) ch; return ch; } #endif #if EN_USART1_RX //如果使能了接收 //串口1中断服务程序 //注意,读取USARTx->SR能避免莫名其妙的错误 u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节. //接收状态 //bit15, 接收完成标志 //bit14, 接收到0x0d //bit13~0, 接收到的有效字节数目 u16 USART_RX_STA=0; //接收状态标记 void uart_init(u32 bound) { //GPIO端口设置 GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟 //USART1_TX GPIOA.9 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9 //USART1_RX GPIOA.10初始化 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入 GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10 //Usart1 NVIC 配置 NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器 //USART 初始化设置 USART_InitStructure.USART_BaudRate = bound;//串口波特率 USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式 USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位 USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式 USART_Init(USART1, &USART_InitStructure); //初始化串口1 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断 USART_Cmd(USART1, ENABLE); //使能串口1 } void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch) { /* 发送一个字节数据到USART */ USART_SendData(pUSARTx,ch); /* 等待发送数据寄存器为空 */ while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET); } void USART1_IRQHandler(void) { uint8_t ucTemp; if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET) { ucTemp = USART_ReceiveData(USART1); uart_receive_input(ucTemp); } USART_ClearFlag(USART1,USART_FLAG_RXNE); } #endif 写一个发送单字节函数,此函数必须,用于向WiFi模组发送数据。 void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch) { /* 发送一个字节数据到USART */ USART_SendData(pUSARTx,ch); /* 等待发送数据寄存器为空 */ while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET); } 2.移植SDK 基础工程搭建完成后将SDK放入工程,记得在keil中添加文件路径。 这个时候要是编译,会疯狂报错,主要是官方方便我们修改。 在下图的函数中填入上面写的串口单字节发送函数 3.确认protocol.h的相关宏定义 1.定义 PID。PRODUCT_KEY 为产品 PID 宏定义。PID 即产品 ID, 为每个产品的唯一标识,可在 IoT 平台的产品详情页面获取。 2.定义 Wi-Fi 模块工作模式。CONFIG_MODE 为配网方式,支持默认模式(AP 和 SmartConfig 互相切换)、安全模式、防误触模式。建议选择防误触模式。 3.定义模块工作方式(必选) 如果配网按键和 LED 接在 MCU 端,即选择模块和 MCU 配合处理工作模式(常用),保持 WIFI_CONTROL_SELF_MODE 宏定义处于被注释状态。 //#define WIFI_CONTROL_SELF_MODE //Wi-Fi 自处理按键及LED指示灯,如为MCU外接按键/LED指示灯请关闭该宏 1 如果配网指示灯和按键是接在 Wi-Fi 模块上的,即选择模块自处理工作模式,开启 WIFI_CONTROL_SELF_MODE 宏定义,然后根据实际的硬件连接,将指示灯和按键所连接的 GPIO 脚位填入下面两个宏定义。 #ifdef WIFI_CONTROL_SELF_MODE //模块自处理 #define WF_STATE_KEY 14 //Wi-Fi 模块状态指示按键,请根据实际 GPIO 管脚设置 #define WF_RESERT_KEY 0 //Wi-Fi 模块重置按键,请根据实际 GPIO 管脚设置 #endif 以上三点较为重要,其他可自行安排,都有相关介绍。 移植protocol.c文件及函数调用 将wifi.h 文件保存至存放 Wi-Fi 相关文件的文件夹中,例如 main.c文件夹。而我是创建了一个WiFi文件夹,WiFi.c只是引用了wifi.h这个头文件,其他为空。 在 MCU 串口及其他外设初始化后调用 mcu_api.c 文件中的 wifi_protocol_init() 函数。 将 MCU 串口单字节发送函数填入 protocol.c 文件中 uart_transmit_output 函数内,并删除 #error。此步骤在上文已介绍。不赘述。 在串口接收中断服务函数里面调用 mcu_api.c 文件内的 uart_receive_input 函数,并将接收到的字符作为参数传入。示例如下: void USART1_IRQHandler(void) { uint8_t ucTemp; if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET) { ucTemp = USART_ReceiveData(USART1); uart_receive_input(ucTemp); } USART_ClearFlag(USART1,USART_FLAG_RXNE); } 在主函数的while(1) 循环后调用 mcu_api.c 文件内的 wifi_uart_service() 函数。该函数用于wifi串口数据处理服务,同时维持心跳。此函数无需任何判断条件,直接调用。在使用该函数时最好不要关闭总中断或串口中断,防止数据丢失,如必要,尽可能短的时间关闭。
3.相关功能完善 1.一键配网功能 配网有两种模式AP配网和smart配网,这里仅介绍smart类型。 配网指令有两个函数可以实现:mcu_reset_wifi() 和 mcu_set_wifi_mode()。通常在按键触发配网后,在按键处理函数中调用。mcu_reset_wifi()调用后复位 Wi-Fi 模组,复位后之前的配网信息全部清除。mcu_reset_wifi() 每调用一次,Wi-Fi 模块即在 AP 和 Smart 之间切换一次配网模式。 mcu_set_wifi_mode()参数为SMART_CONFIG和AP_CONFIG。调用后清除配网信息,进入 Smart 模式或者 AP 模式。值了在按键KEY0中断函数中调用 mcu_get_wifi_work_state() 函数主动获取 Wi-Fi 状态。根据 Wi-Fi 状态,写入相应闪灯的模式。通过switch()判断进入何种状态,状态可选参数如下: exti.c #include "exti.h" #include "led.h" #include "key.h" #include "delay.h" #include "usart.h" //#include "beep.h" #include "mcu_api.h" #include "protocol.h" #include "system.h" #include "wifi.h" #include "lcd.h" #include "text.h" #include "motor.h" //外部中断0服务程序 void EXTIX_Init(void) { EXTI_InitTypeDef EXTI_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; KEY_Init(); // 按键端口初始化 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //使能复用功能时钟 //GPIOE.2 中断线以及中断初始化配置 下降沿触发 GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource2); EXTI_InitStructure.EXTI_Line=EXTI_Line2; //KEY2 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器 //GPIOE.3 中断线以及中断初始化配置 下降沿触发 //KEY1 GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource3); EXTI_InitStructure.EXTI_Line=EXTI_Line3; EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器 //GPIOE.4 中断线以及中断初始化配置 下降沿触发 //KEY0 GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource4); EXTI_InitStructure.EXTI_Line=EXTI_Line4; EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器 //GPIOA.0 中断线以及中断初始化配置 上升沿触发 PA0 WK_UP GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0); EXTI_InitStructure.EXTI_Line=EXTI_Line0; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; EXTI_Init(&EXTI_InitStructure); //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器 NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; //使能按键WK_UP所在的外部中断通道 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2, NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03; //子优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道 NVIC_Init(&NVIC_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn; //使能按键KEY2所在的外部中断通道 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2, NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; //子优先级2 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道 NVIC_Init(&NVIC_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn; //使能按键KEY1所在的外部中断通道 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01; //子优先级1 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道 NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器 NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn; //使能按键KEY0所在的外部中断通道 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级2 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00; //子优先级0 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能外部中断通道 NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器 } //外部中断0服务程序 void EXTI0_IRQHandler(void) { delay_ms(10);//消抖 if(WK_UP==1) //WK_UP按键 { LED0=!LED0; mcu_reset_wifi(); mcu_set_wifi_mode(SMART_CONFIG); // EXTI_ClearITPendingBit(EXTI_Line0); //清除LINE0上的中断标志位 } EXTI_ClearITPendingBit(EXTI_Line0); //清除LINE0上的中断标志位 } //外部中断2服务程序 void EXTI2_IRQHandler(void) { delay_ms(10);//消抖 if(KEY2==0) //按键KEY2 { int i=1000; LED0=!LED0; for(i=1000;i>0;i--) motor_control_F(2); delay_ms(1000); } EXTI_ClearITPendingBit(EXTI_Line2); //清除LINE2上的中断标志位 } //外部中断3服务程序 void EXTI3_IRQHandler(void) { delay_ms(10);//消抖 if(KEY1==0) //按键KEY1 { int i=1000; LED0=!LED0; for(i=1000;i>0;i--) motor_control_Z(2); delay_ms(1000); //LED1=!LED1; } EXTI_ClearITPendingBit(EXTI_Line3); //清除LINE3上的中断标志位 } void EXTI4_IRQHandler(void) { delay_ms(10);//消抖 if(KEY0==0) //按键KEY0 { LED0=!LED0; switch(mcu_get_wifi_work_state()) { case SMART_CONFIG_STATE: Led_Blink_Quick(); POINT_COLOR=BLUE; Show_Str(30,20,200,16,"处于 Smart 配置状态",16,0); break; case AP_STATE: Led_Blink_Slow(); POINT_COLOR=BLUE; Show_Str(30,40,200,16,"处于 AP 配置状态",16,0); break; case WIFI_NOT_CONNECTED: GPIO_ResetBits(GPIOB,GPIO_Pin_5); POINT_COLOR=BLUE; Show_Str(30,60,200,16,"Wi-Fi 配置完成,正在连接路由器",16,0); break; case WIFI_CONNECTED: GPIO_SetBits(GPIOB,GPIO_Pin_5); POINT_COLOR=BLUE; Show_Str(30,80,200,16,"路由器连接成功",16,0); break; case WIFI_CONN_CLOUD: GPIO_SetBits(GPIOB,GPIO_Pin_5); LCD_Clear(WHITE);//清屏 POINT_COLOR=BLUE; Show_Str(30,100,200,16,"WIFI已经连接上云服务器",16,0); break; default:break; } } EXTI_ClearITPendingBit(EXTI_Line4); //清除LINE4上的中断标志位 } 在外部中断函数0里面添加了mcu_reset_wifi(),复位模组,清除全部配网信息,然后调用mcu_set_wifi_mode()函数,参数添加SMART_CONFIG进入smart模式。在这用TFTLCD屏幕显示是否进入smart配网模式,还可显示其他状态。 现在将MCU与模组通过串口1连接,注意TX与RX反接并共地。按下按键,LED快闪,打开手机APP进行配网,当wifi配置完成灯会熄灭,连接上路由器之后灯会重新点亮,并保持常亮。此过程本人已测试无问题,但是过程比较长不适合贴图,会在视频中展示。 2.添加小夜灯等类似功能 配网完成了,那么怎么执行功能呢?在protocol.c中dp_download_handle()函数可以处理下发的数据。在此函数中会对下发的指令进行归类,我们找到小夜灯的处理,这里可以进行小夜灯指令的处理,处理完成之后会上报数据,用于更新APP数据。我们跳转进dp_download_light_handle()函数,此函数中有具体的处理,针对不同的开或关会进入不同的if函数。我们在对LED的端口初始化后便可以将开关灯填入。达到不同下发指令实现开关灯。开关功能类似,不赘述。 3. 添加手动喂食执行功能 这里没有使用涂鸦提供的H桥驱动板,大家要是想要用,直接上一个12V的减速电机,每分钟12转,驱动力大,速度慢,易于控制。将电机接到驱动板的U和V接线柱上,控制口PWM1和PWM2接到单片机PA2和PA3。给PA2和PA3不同的高低电平就可以实现正反转,因为电机本身速度比较慢,就不用软件进行控制速度了。而且因为场景的关系,不用控制正反两个反向,只控制正转和停止。 我在这里用的就不是涂鸦提供的了,步进电机:28BYJ-48,驱动威廉希尔官方网站 :ULN2003芯片的驱动板, motor.c #include "motor.h" #include "delay.h" #include "led.h" #define A1 GPIO_SetBits(GPIOC, GPIO_Pin_3); #define A2 GPIO_ResetBits(GPIOC, GPIO_Pin_3); #define B1 GPIO_SetBits(GPIOC, GPIO_Pin_4); #define B2 GPIO_ResetBits(GPIOC, GPIO_Pin_4); #define C1 GPIO_SetBits(GPIOC, GPIO_Pin_5); #define C2 GPIO_ResetBits(GPIOC, GPIO_Pin_5); #define D1 GPIO_SetBits(GPIOC, GPIO_Pin_6); #define D2 GPIO_ResetBits(GPIOC, GPIO_Pin_6); void motor_configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); //使能PB,PE端口时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6; //PC.012 端口配置 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz GPIO_Init(GPIOC, &GPIO_InitStructure); //根据设定参数初始化GPIOC.5 GPIO_ResetBits(GPIOC,GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6); //PC.012 输出低 } void motor_control_F(int n) { A1; delay_ms(n); A2; B1; delay_ms(n); B2; C1; delay_ms(n); C2; D1; delay_ms(n); D2; } void motor_control_Z(int n) { A1; delay_ms(n); A2; D1; delay_ms(n); D2; C1; delay_ms(n); C2; B1; delay_ms(n); B2; } void Motor_Ctrl_Off(void){ GPIO_ResetBits(GPIOC,GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6); } 编写控制函数,参数为投喂量,通过转动时间来控制投喂量,延时时间需要与宠物的饭盒出粮口搭配,不同出粮口修改延时基数。 随后在dp_download_quick_feed_handle()函数中执行该函数,参数由mcu_get_dp_download_value()函数提供,该函数会提取手机下发的命令。 最后我还加了语音控制功能,下面的文件里有这个工程的全部文件,包括语音模块的设计,就是类似于小度小度那样的智能管家,这里就不在一一介绍了,大家自行下载,看我的演示视频吧。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1885 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1663 浏览 1 评论
1149 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
763 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1720 浏览 2 评论
1965浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
790浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
616浏览 3评论
631浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
593浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-1-14 06:43 , Processed in 0.796981 second(s), Total 75, Slave 59 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (威廉希尔官方网站 图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号