IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 嵌入式计算机系统设计第三次实验报告 -> 正文阅读

[嵌入式]嵌入式计算机系统设计第三次实验报告

实验题目:驱动与API设计初步

实验时间:2022.3.21(周一)~2022.4.3(周日)

实验地点:在规定时间中自主寻找合适实验地点并在规定时间内完成

实验条件:

1.STC-B学习板(2021暑假小学期每个学生自己做的)
2.个人电脑:自备
3.Keil、ISP、CH340驱动软件:自备
4.STC-BSP及Demo 程序:教师提供
5.“STC_B学习板”软件支持包使用说明:教师提供
6.C51语言语法:课程提供参考电子书籍,或自找自学
7.STC_BSP源码示范_sys&显示模块(教师提供源码和工程文件)
8.“STC-B学习板”相关参考程序_夏季小学期相关案例
9. 步进电机(C栋214提供调式用步进电机)

实验目的:

1.学习并练习“并口输出”应用和编程;
2.参照所提供的STC-BSP核心sys源码和显示模块源码,学习软件设计的层次化抽象方法并实践;
3.实验具体目的是:针对“无人驾驶汽车”应用场景,设计具有同时控制三个步进功能的程序模块,该模块能提供适当的API函数(一个或多个),方便应用层编写控制电机程序。

实验内容:

1.查找资料,熟悉四线步进电机控制方法;
2.阅读所提供的displayer模块参考源程序和其API函数设计方法,规划构造控制三个步进电机程序模块的API函数(一个或多个函数)。三个步进电机分别假设为:SM接口(可接1个真实步进电机)、8个LED指示灯(假设为另外2个步进电机控制接口);
3.从模块的初始化程序、后台服务程序(驱动程序)、应用层接口API函数三个层次设计该模块对应程序,最终实现你所规划的API函数,并验证API函数的正确性。(暂不要求按模板方式封装);

实验过程、步骤、现象、结果:

查找资料,熟悉四线步进电机控制方法:

28BYJ-48型步进电机的旋转是以固定的角度一步一步运行的。可以通过控制脉冲个数来控制角位移量,从而达到准确定位的目的;同时可以通过控制脉冲频率来控制电机转动的速度和加速度,从而达到调速的目的。控制步进电机定子绕组的通电顺序可以控制步进电机的转动方向。28BYJ-48型接线图如图1所示。
在这里插入图片描述

图1 28BYJ-48步进电机控制接线
步进电机的励磁方式有三种:
(1)一相励磁——在每一瞬间,步进电机只有一个线圈导通。每送一个励磁信号,步进电机旋转5.625°,这是三种励磁方式中最简单的一种。
如图7-3-2所示,开始时,开关SB接通电源,SA、SC、SD断开,B相磁极和转子0、3号齿对齐,同时,转子的1、4号齿就和C、D相绕组磁极产生小角度错齿,2、5号齿就和D、A相绕组磁极产生大角度(前小角度的2倍)错齿。
当开关SC接通电源,SB、SA、SD断开时,由于C相绕组的磁力线和1、4号齿之间磁力线的作用,使转子转动,1、4号齿和C相绕组的磁极对齐。而0、3号齿和A、B相绕组产生错齿,2、5号齿就和A、D相绕组磁极产生错齿。依次类推,A、B、C、D四相绕组轮流供电,则转子会沿着A、B、C、D方向转动。
在这里插入图片描述

(2)二相励磁——在每一瞬间,步进电机有两个线圈同时导通。每送一个励磁信号,步进电机旋转5.625°。1/64
在这里插入图片描述

(3)一-二相励磁——为一相励磁与二相励磁交替导通的方式。每送一个励磁信号,步进电机旋转2.8125°。八拍模式是这类四相步进电机的最佳工作模式,能最大限度的发挥电机的各项性能。当相邻两相同时导通的节拍时,由于该两相绕组的定子齿对它们附近的转子齿同时产生相同的吸引力,这将导致这两个转子齿的中心线对到两个绕组的中心线上,也就使转动精度增加了一倍,还会增加电机的整体扭力输出。
在这里插入图片描述

学习板上步进电机电路图如图2所示,一路高电平信号由IO端输出经ULN2003取反为低电平输入至步进电机驱动一相绕组。
在这里插入图片描述

图2 步进电机电路示意

阅读所提供的displayer模块参考源程序和其API函数设计方法,规划构造控制三个步进电机程序模块的API函数(一个或多个函数)。三个步进电机分别假设为:SM接口(可接1个真实步进电机)、8个LED指示灯(假设为另外2个步进电机控制接口);

对于显示模块的实现:首先是初始化函数也就是显示模块的驱动,这里即是设置P0寄存器(用于控制LED和数码管段选的寄存器)8位为推挽输出,这样可以是的输出的亮度更大。
在这里插入图片描述

驱动之后是显示模块:
该显示模块首先对P2寄存器地4位进行赋值(下面的switch)若要输出LED则这低4位的最高位为1,显示数码管时为0,第3位在选择数码管时有效,表示显示8位数码管的第几号数码管,后续则是对数码管显示的译码和计算下一次要显示的位置(第几号数码管或者LED),最后只要我们对该函数进行每1ms一次的循环运行就能使我们的数码管和LED正常显示(虽然每次只能显示一个地方,但间隔时间短,所以肉眼看不出来)
在这里插入图片描述

最后则是一些修改参数的API函数:
在这里插入图片描述

对于sys模块的实现:sys模块主要用于实现系统基本的中断处理函数的实现
比如这里sys用于设置定时器和开启定时器中断:
在这里插入图片描述

然后MySTC_OS将会不断的运行(即放入while(1)死循环中),每次对标志位进行判断(每个标志位表示系统运行了多少时间了),标志位的更新通过1ms的定时器来完成
在这里插入图片描述
在这里插入图片描述

其他的标志位通过对1ms事件的计数即可实现。
然后在1ms事件中加入上面的显示轮询函数或者其他需要的函数,即可实现显示操作(而不会全占系统资源,导致其他功能无法运行)。

从模块的初始化程序、后台服务程序(驱动程序)、应用层接口API函数三个层次设计该模块对应程序,最终实现你所规划的API函数,并验证API函数的正确性。(暂不要求按模板方式封装);

驱动部分:将A,B,C,D电圈对应的引脚p4的低4位设置为推挽输出,然后初始化p4为0
在这里插入图片描述

电机运行函数:将该函数放到和显示模块的地方,每1ms进行轮询运行(这里使用的老师的BSP环境,不能直接修改sys中的函数,所以用1ms的回调事件代替)
在这里插入图片描述

分为3个部分分别对应于电机1,2,3其中电机1位真实电机,通过判断每个电机的速度,剩余转动步长以及转动频率(即每多少ms转动一次,通过1000/speed进行计算)来判断每个电机是否旋转。
在这里插入图片描述

旋转时对于虚拟电机2,3通过LED灯进行模拟速度和方向,先进行step的正负判断,这决定电机的旋转方向,随后将LED向相应方向移动一位,并重置延时和将剩余转动步长减1。虚拟电机3同理,只是LED的流动部分在LED的高4位。

在这里插入图片描述

对于真实电机1而言,根据电机的资料,A,B,C,D,4个线圈分别运行一次后电机旋转1/64 * 4=1/16圈,所以重复该步骤16次即完成电机一圈的旋转。其余操作和虚拟电机一致,实现代码如下,反转代码将顺序改为D,C,B,A即可

最后实现改变电机参数的函数:
在这里插入图片描述

该函数作用为对电机1,2,3进行速度和剩余旋转步数的设置,经过设置后电机就可以正常旋转,函数的使用与老师BSP中电机的相应函数使用方法一致
急停函数:紧急停止某一电机
根据电机,将相应电机速度置0,然后返回剩余的旋转步数。
在这里插入图片描述

状态查询函数:
在这里插入图片描述

根据电机是否有剩余步数,返回电机是否空闲

最后运行程序1:测试速度调整
在这里插入图片描述

首先的初始化部分,需要先运行电机的初始化函数,随后需要将电机的运行函数放到1ms的回调事件中(原因上文已说明)
另外两个回调函数,分别用于调整电机速度和显示当前待设置的电机序号和该电机的速度。
在这里插入图片描述

按键3用于调整,要设置的电机序号,按键1,2分别用于增加和减少电机的运行速度,代码详情如图所示(按键2同理这里就没贴出来)

最后没10ms更新一次显示内容即可
在这里插入图片描述

运行效果:
可以看到目前扩展接口SM的4个引脚灯,正在按照电机运行顺序发光,说明我们的电机驱动程序是成功的,而8个LED灯部分则是在模拟电机的运行。
在这里插入图片描述

运行程序2:测试方向调整
总体代码与程序2类似,按键1改为对电机进行急停操作,按键2改为对电机进行反向操作
显示部分改为显示电机的剩余步长
运行效果:
初始化时设置的电机旋转步数为10000。
在这里插入图片描述

实验遇到的问题和难点

在测试速度时将速度调整为0 后LED灯正常停止,但再次将速度调整为大于0时,LED会停止一段时间后才开始移动
产生原因:
一开始我在电机运行函数中判断电机是否旋转的条件写的是如下方式:
在这里插入图片描述

问题就出现在如果speed1调整到0后,当delay1减为0后,电机不会运行旋转的程序以及该程序中的重置delay1的程序,导致delay1减到负数,但因为我定义的类型为unsigned int所以会使得delay1变为2^16,从而出现上面,将速度调回大于0后任要过一段时间后才会运行LED灯。
解决方式:将speed条件单独拿出来即可
在这里插入图片描述

完整代码

电机头文件代码(代码供以参考,要copy的话记得改下变量名和顺序):
头文件命名为motor.h

#include "STC15F2K60S2.H"
#include "displayer.H"
#include "beep.h"

sbit s1 =P4^1;												    //步进电机IO口
sbit s2 =P4^2;
sbit s3 =P4^3;
sbit s4 =P4^4;
unsigned int delay1=0,delay2=0,delay3=0,i1=0,i2=0,i,j;
unsigned char led=0;
unsigned char speed1;
unsigned char speed2;
unsigned char speed3;
int steps;
int steps1=0;
int steps2=0;
int steps3=0;
enum StepMotorName    {enumStepMotor1=0,enumStepMotor2,enumStepMotor3};//motor1为真实电机
enum StepMotorActName {enumStepMotorFree,enumStepMotorBusy,enumSetStepMotorOK,enumSetStepMotorFail};

void delay_ms( unsigned int n)//延时函数1ms		
{
 while(n)
  {
	unsigned char i, j;
	i = 11;
	j = 190;
	do
	{
		while (--j);
	} while (--i);
	n--;
  }
}
void MotorInit()			  
{																//P4口推挽输出
  P4M0=0Xff;
	P4M1=0X00;
	P4  =0X00;												    //P4口设置低电平,避免复位时对步进电机5V电平接口的影响
}
void PlayMotor() //电机运行一圈
{
  if (speed1 != 0)
    if (delay1-- == 0 && steps1 != 0)
    {
      if (steps1 > 0) //正转
      {
        for (j = 0; j < 16; j++) //转一圈
        {
          s1 = 1;
          s2 = 0;
          s3 = 0;
          s4 = 0;
          s1 = 0;
          s2 = 1;
          s3 = 0;
          s4 = 0;
          s1 = 0;
          s2 = 0;
          s3 = 1;
          s4 = 0;
          s1 = 0;
          s2 = 0;
          s3 = 0;
          s4 = 1;
        }
        steps1--;
        delay1 = 1000 / speed1;
      }
      else //反转
      {
        for (j = 0; j < 16; j++) //转一圈
        {
          s1 = 0;
          s2 = 0;
          s3 = 0;
          s4 = 1;
          s1 = 0;
          s2 = 0;
          s3 = 1;
          s4 = 0;
          s1 = 0;
          s2 = 1;
          s3 = 0;
          s4 = 0;
          s1 = 1;
          s2 = 0;
          s3 = 0;
          s4 = 0;
        }
        steps1++;
        delay1 = 1000 / speed1;
      }
    }
  if (speed2 != 0)
    if (delay2-- == 0 && steps2 != 0)
    {
      if (steps2 > 0)
      {
        led = (led & 0xf0) + (0x01 << (i1 % 4));
        LedPrint(led);
        i1++;
        steps2--;
        delay2 = 1000 / speed2;
      }
      else
      {
        led = (led & 0xf0) + (0x08 >> (i1 % 4));
        LedPrint(led);
        i1++;
        steps2++;
        delay2 = 1000 / speed2;
      }
    }
  if (speed3 != 0)
    if (delay3-- == 0 && steps3 != 0)
    {
      if (steps3 > 0)
      {
        led = (led & 0x0f) + (0x10 << (i2 % 4));
        LedPrint(led);
        i2++;
        steps3--;
        delay3 = 1000 / speed3;
      }
      else
      {
        led = (led & 0x0f) + (0x80 >> (i2 % 4));
        LedPrint(led);
        i2++;
        steps3++;
        delay3 = 1000 / speed3;
      }
    }
}
char SetMotor(char StepMotor, unsigned char speed, int steps)
{
  switch (StepMotor)
  {
  case enumStepMotor1: //真实电机
    steps1 = steps;
    speed1 = speed;
    return enumSetStepMotorOK;
  case enumStepMotor2: //虚拟电机LED0~LED3
    steps2 = steps;
    speed2 = speed;
    return enumSetStepMotorOK;
  case enumStepMotor3:
    steps3 = steps;
    speed3 = speed;
    return enumSetStepMotorOK;
  default:
    return enumSetStepMotorFail;
  }
}
int EmStop(char StepMotor)
{
  switch (StepMotor)
  {
  case enumStepMotor1:
    steps = steps1;
    steps1 = 0;
    return steps;
  case enumStepMotor2:
    steps = steps2;
    steps2 = 0;
    return steps;
  case enumStepMotor3:
    steps = steps3;
    steps3 = 0;
    return steps;
  default:
    return 0;
  }
}
unsigned char GetMotorStatus(char StepMotor)
{
  switch (StepMotor)
  {
  case enumStepMotor1:
    if (steps1 == 0)
      return enumStepMotorFree;
    else
      return enumStepMotorBusy;
  case enumStepMotor2:
    if (steps2 == 0)
      return enumStepMotorFree;
    else
      return enumStepMotorBusy;
  case enumStepMotor3:
    if (steps3 == 0)
      return enumStepMotorFree;
    else
      return enumStepMotorBusy;
  default:
    return enumSetStepMotorFail;
  }
} 


测试代码:速度测试(为什么不把两个功能写在一起?当然是我嫌麻烦不想用导航按键)

//功能:双通道秒表,K3、K1独立控制两个秒表计时开始和结束,计时分辨率0.01S
#include "STC15F2K60S2.H"
#include "beep.h"
#include "Key.h"
#include "sys.h"
#include "motor.h"
#include "STC15F2K60S2.H"
#include "displayer.h"

// void key_callback()
// {
//   if(GetKeyAct(enumKey1)==enumKeyPress)
//   SetMotor(enumStepMotor2,0x01,10);
// }
enum StepMotorName Motor=enumStepMotor1;
unsigned char MotorSpeed1=0x01;
unsigned char MotorSpeed2=0x01;
unsigned char MotorSpeed3=0x01;
void Motor_CallBack()
{
  PlayMotor();
}
void key_callback()
{
  if (GetKeyAct(enumKey3) == enumKeyPress)
  {
    SetBeep(1000, 10);
    if (Motor < 2)
      Motor++;
    else
      Motor = enumStepMotor1;
  }
  if (GetKeyAct(enumKey1) == enumKeyPress)
  {
    SetBeep(1000,10);
    switch (Motor)
    {
    case enumStepMotor1:
      if (MotorSpeed1 != 0xff)
        MotorSpeed1++;
      SetMotor(enumStepMotor1, MotorSpeed1, steps1);
      break;
    case enumStepMotor2:
      if (MotorSpeed2 != 0xff)
        MotorSpeed2++;
      SetMotor(enumStepMotor2, MotorSpeed2, steps2);
      break;
    case enumStepMotor3:
      if (MotorSpeed3 != 0xff)
        MotorSpeed3++;
      SetMotor(enumStepMotor3, MotorSpeed3, steps3);
      break;
    }
  }
  if (GetKeyAct(enumKey2) == enumKeyPress)
  {
    SetBeep(1000,10);
    switch (Motor)
    {
    case enumStepMotor1:
      if (MotorSpeed1 != 0x00)
        MotorSpeed1--;
      SetMotor(enumStepMotor1, MotorSpeed1, steps1);
      break;
    case enumStepMotor2:
      if (MotorSpeed2 != 0x00)
        MotorSpeed2--;
      SetMotor(enumStepMotor2, MotorSpeed2, steps2);
      break;
    case enumStepMotor3:
      if (MotorSpeed3 != 0x00)
        MotorSpeed3--;
      SetMotor(enumStepMotor3, MotorSpeed3, steps3);
      break;
    }
  }
}
void Display_CallBack()
{
  switch (Motor)
  {
  case enumStepMotor1:
    Seg7Print(Motor + 1, 10, 10, 10, 10, MotorSpeed1 / 100 % 10, MotorSpeed1 / 10 % 10, MotorSpeed1 % 10);
    break;
  case enumStepMotor2:
    Seg7Print(Motor + 1, 10, 10, 10, 10, MotorSpeed2 / 100 % 10, MotorSpeed2 / 10 % 10, MotorSpeed2 % 10);
    break;
  case enumStepMotor3:
    Seg7Print(Motor + 1, 10, 10, 10, 10, MotorSpeed3 / 100 % 10, MotorSpeed3 / 10 % 10, MotorSpeed3 % 10);
    break;
  }
}
code unsigned long SysClock=11059200;         //必须。定义系统工作时钟频率(Hz),用户必须修改成与实际工作频率(下载时选择的)一致

#ifdef _displayer_H_                          //显示模块选用时必须。(数码管显示译码表,用戶可修改、增加等) 
code char decode_table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x08,0x40,0x01, 0x41, 0x48, 
	              /* 序号:   0   1    2	   3    4	    5    6	  7   8	   9	 10	   11		12   13    14     15     */
                /* 显示:   0   1    2    3    4     5    6    7   8    9  (无)   下-  中-  上-  上中-  中下-   */  
	                       0x3f|0x80,0x06|0x80,0x5b|0x80,0x4f|0x80,0x66|0x80,0x6d|0x80,0x7d|0x80,0x07|0x80,0x7f|0x80,0x6f|0x80 };  
             /* 带小数点     0         1         2         3         4         5         6         7         8         9        */
#endif

void main()
{ 
  DisplayerInit();
	BeepInit();
	Key_Init();
  MotorInit();
  SetDisplayerArea(0,7);
  Seg7Print(10,10,10,10,10,10,10,10);

  SetEventCallBack(enumEventKey,key_callback);
  SetEventCallBack(enumEventSys1mS,Motor_CallBack);
  SetEventCallBack(enumEventSys10mS,Display_CallBack);
  SetMotor(enumStepMotor1,MotorSpeed1,10000);
  SetMotor(enumStepMotor2,MotorSpeed2,10000);
  SetMotor(enumStepMotor3,MotorSpeed3,10000);
  MySTC_Init();
  while (1)
  {
    MySTC_OS();
  }
}

方向,急停测试:

//功能:双通道秒表,K3、K1独立控制两个秒表计时开始和结束,计时分辨率0.01S
#include "STC15F2K60S2.H"
#include "beep.h"
#include "Key.h"
#include "sys.h"
#include "motor.h"
#include "STC15F2K60S2.H"
#include "displayer.h"

// void key_callback()
// {
//   if(GetKeyAct(enumKey1)==enumKeyPress)
//   SetMotor(enumStepMotor2,0x01,10);
// }
enum StepMotorName Motor=enumStepMotor1;
unsigned char MotorSpeed1=0x01;
unsigned char MotorSpeed2=0x01;
unsigned char MotorSpeed3=0x01;
void Motor_CallBack()
{
  PlayMotor();
}
void key_callback()
{
  if (GetKeyAct(enumKey3) == enumKeyPress)
  {
    SetBeep(1000, 10);
    if (Motor < 2)
      Motor++;
    else
      Motor = enumStepMotor1;
  }
  if (GetKeyAct(enumKey1) == enumKeyPress)
  {
    SetBeep(1000,10);
    switch (Motor)
    {
    case enumStepMotor1:
      EmStop(enumStepMotor1);
      break;
    case enumStepMotor2:
      EmStop(enumStepMotor2);
      break;
    case enumStepMotor3:
      EmStop(enumStepMotor3);
      break;
    }
  }
  if (GetKeyAct(enumKey2) == enumKeyPress)
  {
    SetBeep(1000,10);
    switch (Motor)
    {
    case enumStepMotor1:
      SetMotor(enumStepMotor1, MotorSpeed1, -steps1);
      break;
    case enumStepMotor2:
      SetMotor(enumStepMotor2, MotorSpeed2, -steps2);
      break;
    case enumStepMotor3:
      SetMotor(enumStepMotor3, MotorSpeed3, -steps3);
      break;
    }
  }
}
int abs(int n)
{
  if(n>0)
  return n;
  else
  return -n;
}
void Display_CallBack()
{
  switch (Motor)
  {
  case enumStepMotor1:
    Seg7Print(Motor + 1, 10, 10, abs(steps1)/10000%10, abs(steps1)/1000%10, abs(steps1)/100%10, abs(steps1)/10%10, abs(steps1)%10);
    break;
  case enumStepMotor2:
    Seg7Print(Motor + 1, 10, 10, abs(steps2)/10000%10, abs(steps2)/1000%10, abs(steps2)/100%10, abs(steps2)/10%10, abs(steps2)%10);
    break;
  case enumStepMotor3:
    Seg7Print(Motor + 1, 10, 10, abs(steps3)/10000%10, abs(steps3)/1000%10, abs(steps3)/100%10, abs(steps3)/10%10, abs(steps3)%10);
    break;
  }
}
code unsigned long SysClock=11059200;         //必须。定义系统工作时钟频率(Hz),用户必须修改成与实际工作频率(下载时选择的)一致

#ifdef _displayer_H_                          //显示模块选用时必须。(数码管显示译码表,用戶可修改、增加等) 
code char decode_table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x08,0x40,0x01, 0x41, 0x48, 
	              /* 序号:   0   1    2	   3    4	    5    6	  7   8	   9	 10	   11		12   13    14     15     */
                /* 显示:   0   1    2    3    4     5    6    7   8    9  (无)   下-  中-  上-  上中-  中下-   */  
	                       0x3f|0x80,0x06|0x80,0x5b|0x80,0x4f|0x80,0x66|0x80,0x6d|0x80,0x7d|0x80,0x07|0x80,0x7f|0x80,0x6f|0x80 };  
             /* 带小数点     0         1         2         3         4         5         6         7         8         9        */
#endif

void main()
{ 
  DisplayerInit();
	BeepInit();
	Key_Init();
  MotorInit();
  SetDisplayerArea(0,7);
  Seg7Print(10,10,10,10,10,10,10,10);

  SetEventCallBack(enumEventKey,key_callback);
  SetEventCallBack(enumEventSys1mS,Motor_CallBack);
  SetEventCallBack(enumEventSys10mS,Display_CallBack);
  SetMotor(enumStepMotor1,MotorSpeed1,10000);
  SetMotor(enumStepMotor2,MotorSpeed2,10000);
  SetMotor(enumStepMotor3,MotorSpeed3,10000);
  MySTC_Init();
  while (1)
  {
    MySTC_OS();
  }
}
  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-04-01 23:35:27  更:2022-04-01 23:36:01 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 5:41:03-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码