06:(寄存器开发)定时器二

定时器二

1、通用定时器

1.1、输出比较功能

stm32f103c8t6的通用定时器为TIM2,TIM3,TIM4。而通用定时器拥有基本定时器的所有功能,并且增加的如下的功能:

(1)多种时钟源选择

(2)向上计数(加),向下计数(减),向上/向下(先加后减)。当然我们使用的时候更喜欢向上计数

(3)输出比较,用于测量波形的周期/测量脉冲的宽度

(4)输入捕获,用于PWM波形的生成

(5)支持针对定位的增量(正交)编码器和霍尔传感器电路。

下图为通用定时器的结构框图(时钟来源,输入捕获,输出比较,从模式):

实验:使用TIM2的输出比较CH1输出PWM波形实现呼吸灯。实物连接如下图所示:

①TIM2.c文件的代码如下:

c 复制代码
#include "stm32f10x.h"                

/**
 * 通用定时器的输出比较模式输出PWM波形的初始化
 */
void TIM2_Init(void)
{
    /* 1、开启时钟 */
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;//开启GPIOA的时钟
    RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;//开启TIM2的时钟
    
    /* 2、配置GPIOA0(TIM2_CH1)引脚输出模式:复用推挽输出(MODE0 = 11,CNF0 = 10)*/
    GPIOA->CRL |= GPIO_CRL_MODE0;
    GPIOA->CRL &= ~GPIO_CRL_CNF0_0;
    GPIOA->CRL |= GPIO_CRL_CNF0_1;

    /* 3、定时器TIM2的配置 */
    /* 3.0、选择时钟源,默认的是内部时钟源ABP1*/
    
    /* 3.1、预分频器的设置 */
    TIM2->PSC = 7200 - 1;//每隔0.1ms来一个脉冲,计数一次

    /* 3.2、自动重装载寄存器的设置 */
    TIM2->ARR = 100 - 1;//一个周期的时间为10ms

    /* 3.3、计数器的计数方向:默认向上计数*/
    TIM2->CR1 &= ~TIM_CR1_DIR;//向上计数

    /* 4、配置输出比较 */
    /* 4.1、配置捕获比较寄存器的值 */
    TIM2->CCR1 = 50;

    /* 4.2、配置通道CH1的输出比较模式: TIMx_CCMR1_CC1S = 00(输出模式)
        TIMx_CCMR1_OC1M = 110(PWM1模式)
    */
    TIM2->CCMR1 &= ~TIM_CCMR1_CC1S;//CH1配置为输出模式
    TIM2->CCMR1 &= ~TIM_CCMR1_OC1M_0;
    TIM2->CCMR1 |= TIM_CCMR1_OC1M_1;
    TIM2->CCMR1 |= TIM_CCMR1_OC1M_2;

    /* 4.3、使能通道1:TIMx_CCER_CC1E = 1 */
    TIM2->CCER |= TIM_CCER_CC1E;//使能通道CH1

    /* 5、使能计数器 */
    TIM2->CR1 |= TIM_CR1_CEN;
}

/**
 * 更改占空比函数
 */
void Set_PWMDuty(uint8_t Data)
{
    TIM2->CCR1 = Data;
}

②主函数文件的代码如下:

c 复制代码
#include "stm32f10x.h"                
#include "TIM2.h"
#include "OLED.h"
#include "Delay.h"

int main(void)
{
    uint8_t Data = 0;
    TIM2_Init();
    Set_PWMDuty(Data);
	while(1)
	{
        for(uint8_t i = 0; i<100; i++)
        {
            Set_PWMDuty(++Data);
            Delay_ms(10);
        }
        for(uint8_t i = 0; i<100; i++)
        {
            Set_PWMDuty(--Data);
            Delay_ms(10);
        }
	}
}

实物效果展示如下:

呼吸灯

1.2、输入捕获功能

此功能可以捕获输入通道上输入信号的上升沿或下降沿,多用于测量PWM的周期/频率,也可以测量占空比,只要测量出连续的一个上升沿和一个下降沿的时间间隔,然后除以周期即可。

测量的方法如下:①只要测量出连续的两个上升沿或连续的两个下降沿的时间间隔。②在1s时间内捕获了N个上升沿,那么则1s内有N-1个周期,计算出周期,那么就能计算出频率。

通用定时器能产生中断的部位如下:

1.2.1、测量PWM波形的周期和频率

实验:使用TIM3的输入捕获CH1通道测量出TIM2产生的PWM波形的周期与频率
①TIM3.c文件的代码如下;

c 复制代码
#include "stm32f10x.h"                 

/**
 * 通用定时器TIM3的初始化,使用输出捕获通道CH1测量TIM2产生的PWM波形的频率和周期
 */
void TIM3_Init(void)
{
/* 1、开启时钟 */
    /* 1.1、开启定时器TIM3和CH1通道引脚(PA6)的时钟 */
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;//开启GPIOA的时钟
    RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;//开启TIM3的时钟

/* 2、配置CH1通道引脚为浮空输入模式:MODE6 = 00,CNF6 = 01 */
    GPIOA->CRL &= ~GPIO_CRL_MODE6;
    GPIOA->CRL |= GPIO_CRL_CNF6_0;
    GPIOA->CRL &= ~GPIO_CRL_CNF6_1;

/* 3、配置基本定时器TIM3 */
    /* 3.1、选择时钟源 */
    //默认为内部时钟源,所以无需代码配置

    /* 3.2、配置预分频PSC,分频系数为72 */
    TIM3->PSC = 72 - 1;//则一个脉冲的时间为1us

    /* 3.3、配置重装在值,为了防止溢出,配置最大*/
    TIM3->ARR = 65536 - 1;

    /* 3.4、配置计数器为向上计数:TIMx_CR1_DIR = 0 */
    TIM3->CR1 &= ~TIM_CR1_DIR;

/* 4、配置输入捕获相关寄存器 */
    /* 4.1、TIMx_CH1引脚连到TI1输入:TIMx_CR2_TI1S = 0 */
    TIM3->CR2 &= ~TIM_CR2_TI1S;

    /* 4.2、输入滤波器的配置,配置为不滤波:TIMx_CCMR1_IC1F = 0000 */
    TIM3->CCMR1 &= ~TIM_CCMR1_IC1F;
    
    /* 4.3、将CH1通道配置为输入捕获模式,且IC1映射到TI1::TIMx_CCMR1_CC1S = 01 */
    TIM3->CCMR1 |= TIM_CCMR1_CC1S_0;
    TIM3->CCMR1 &= ~TIM_CCMR1_CC1S_1;//IC1映射在TI1上

    /* 4.4、配置为捕获上升沿:TIMx_CCER_CC1P = 0 */
    TIM3->CCER &= ~TIM_CCER_CC1P;

    /* 4.5、输入捕获中的预分频的配置(不分频):TIMx_CCMR1_IC1PSC = 00 */
    TIM3->CCMR1 &= ~TIM_CCMR1_IC1PSC;

    /* 4.6、开启中断请求:TIMx_DIER_CC1IE = 1 */
    TIM3->DIER |= TIM_DIER_CC1IE;

    /* 4.7、使能捕获/比较寄存器:TIMx_CCER_CC1E = 1*/
    TIM3->CCER |= TIM_CCER_CC1E;

/* 5、配置NVIC */
    NVIC_SetPriorityGrouping(4);
    NVIC_SetPriority(TIM3_IRQn,0);
    NVIC_EnableIRQ(TIM3_IRQn);

/* 6、使能计数器:TIMx_CR1_CEN = 1*/
    TIM3->CR1 |= TIM_CR1_CEN;
}

/**
 * 中断服务函数:在捕获到第一个上升沿,让计数器里面的值变为0
 * 当捕获到第二个上升沿时,计数器里面的值拍照到捕获/比较寄存器(CCR)里面(硬件自动完成的)
 */
uint16_t t = 0;
void TIM3_IRQHandler(void)
{
    static uint8_t flag = 0;//第一个一个标志位,用来判断是否为第一个上升沿
    if(TIM3->SR & TIM_SR_CC1IF)
    {
        /* 清除标志位:TIMx_SR_CC1IF*/
        TIM3->SR &= ~TIM_SR_CC1IF;
        flag++;
        /* 判断是否为第一次上升沿,若是那么就清除计数器里面的值*/
        if(flag == 1)
        {
            TIM3->CNT = 0;//将计数器里面的值变为0
            TIM3->CCR1 = 0;//将捕获/比较寄存器(CCR)里面的值也变为0
        }
        else if(flag == 2)
        {
            t = TIM3->CCR1;//将计数器里面的值拍照到捕获/比较寄存器(CCR)里面
            TIM3->CNT = 0;//将计数器里面的值变为0
            TIM3->CCR1 = 0;//将捕获/比较寄存器(CCR)里面的值也变为0
            flag = 0;//让flag = 0;
        }
    }
}

/**
 * 对将捕获/比较寄存器(CCR)里面的值进行处理,获取PWM波形的周期(us)
 */
double Get_PWMCycle(void)
{
    return t ;//返回为us
}

/**
 * 对将捕获/比较寄存器(CCR)里面的值进行处理,获取PWM波形的频率(Hz)
 */
double Get_PWMFrequency(void)
{
    return 1000000.0 / t;//返回为Hz
}

TIM2.c文件的代码如下:

c 复制代码
#include "stm32f10x.h"                


/**
 * 通用定时器的输出比较模式输出PWM波形的初始化
 */
void TIM2_Init(void)
{
    /* 1、开启时钟 */
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;//开启GPIOA的时钟
    RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;//开启TIM2的时钟
    
    /* 2、配置GPIOA0(TIM2_CH1)引脚输出模式:复用推挽输出(MODE0 = 11,CNF0 = 10)*/
    GPIOA->CRL |= GPIO_CRL_MODE0;
    GPIOA->CRL &= ~GPIO_CRL_CNF0_0;
    GPIOA->CRL |= GPIO_CRL_CNF0_1;

    /* 3、定时器TIM2的配置 */
    /* 3.0、选择时钟源,默认的是内部时钟源ABP1*/
    
    /* 3.1、预分频器的设置 */
    TIM2->PSC = 7200 - 1;//每隔0.1ms来一个脉冲,计数一次

    /* 3.2、自动重装载寄存器的设置 */
    TIM2->ARR = 100 - 1;//一个周期的时间为10ms

    /* 3.3、计数器的计数方向:默认向上计数*/
    TIM2->CR1 &= ~TIM_CR1_DIR;//向上计数

    /* 4、配置输出比较 */
    /* 4.1、配置捕获比较寄存器的值 */
    TIM2->CCR1 = 50;

    /* 4.2、配置通道CH1的输出比较模式: TIMx_CCMR1_CC1S = 00(输出模式)
        TIMx_CCMR1_OC1M = 110(PWM1模式)
    */
    TIM2->CCMR1 &= ~TIM_CCMR1_CC1S;//CH1配置为输出模式
    TIM2->CCMR1 &= ~TIM_CCMR1_OC1M_0;
    TIM2->CCMR1 |= TIM_CCMR1_OC1M_1;
    TIM2->CCMR1 |= TIM_CCMR1_OC1M_2;

    /* 4.3、使能通道1:TIMx_CCER_CC1E = 1 */
    TIM2->CCER |= TIM_CCER_CC1E;//使能通道CH1

    /* 5、使能计数器 */
    TIM2->CR1 |= TIM_CR1_CEN;
}

/**
 * 更改占空比函数
 */
void Set_PWMDuty(uint8_t Data)
{
    TIM2->CCR1 = Data;
}

③主函数文件的代码如下:

c 复制代码
#include "stm32f10x.h"                
#include "TIM2.h"
#include "TIM3.h"
#include "OLED.h"

int main(void)
{ 
    uint8_t Data = 0;
    OLED_Init();
    OLED_ShowString(1,1,"Cycle:00000us");
    OLED_ShowString(2,1,"Freq:0000Hz");

    TIM2_Init();//TIM2的初始化,产生了一个周期为10ms的PWM波形
    TIM3_Init();//TIM3的初始化,开启CH1输出捕获
    Set_PWMDuty(Data);
    
	while(1)
	{
       OLED_ShowNum(1,7,Get_PWMCycle(),5);
       OLED_ShowNum(2,6,Get_PWMFrequency(),4);
        
       for(uint8_t i = 0; i<100; i++)
       {
           Set_PWMDuty(++Data);
           Delay_ms(10);
       }
       for(uint8_t i = 0; i<100; i++)
       {
           Set_PWMDuty(--Data);
           Delay_ms(10);
       }
	}
}

实物演示效果如下:

测量PWM周期和频率

1.2.2、定时器的从模式

使用TIM3的输入捕获CH1通道测量出TIM2产生的PWM波形的周期与频率这个实验,捕获到第一个上升沿的时候我们使用中断的方式,在中断函数里面通过CPU执行代码让计数器里面的值变为0。这样的方式测量出来的一个周期的CRR的值是有误差的。

因为在第一个上升沿来的时候触发中断,在执行中断函数的时候,PWM波形不断的"走",当执行到清零计数器的代码的时候,PWM波形已经走了一会了。所以不是在检测到PWM波形的上升沿的同一时间就立马把计数器里面的数据清零。但是,将计数器中的数据拍照到CRR中是由硬件执行的,在检测到上升沿时,硬件立马会把计数器中的数据拍照到CRR寄存器中。所以,使用上面的实验的方法,测量出来的周期一般比实际周期小。

为了解决这一问题:使用定时器的从模式。从模式的功能都是由硬件自动完成的,无需CPU执行代码。

如上图所示:TRGI为从模式触发信号,其中触发信号的来源如图中蓝色框中的8种,如下图为8中信号来源。
从模式的工作方式:

实验:通过定时器从模式自动测量PWM波的周期和频率和PWM波的占空比。

从模式的触发信号选择TI1FP1,从模式的工作模式为复位模式。将IC1配置为检测上升沿,且IC1映射在TI1FP1。将IC2配置为检测下降沿,且IC2映射在TI1FP2。即来一个上升沿时,通过从模式硬件自动启动复位(计数器清零),来一个下降沿计数器里面的值拍照到捕获/比较寄存器2中CCR2。再来一个上升沿将计数器里面值拍照到CCR1中。则一个周期 = CCR1里面的数值,占空比 = CCR2/CCR1

①TIM3.c文件的代码如下:

c 复制代码
#include "stm32f10x.h"                 

/**
 * 通用定时器TIM3的初始化,使用输出捕获通道CH1测量TIM2产生的PWM波形的频率和周期
 */
void TIM3_Init(void)
{
/* 1、开启时钟 */
    /* 1.1、开启定时器TIM3和CH1通道引脚(PA6)的时钟 */
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;//开启GPIOA的时钟
    RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;//开启TIM3的时钟

/* 2、配置CH1通道引脚为浮空输入模式:MODE6 = 00,CNF6 = 01 */
    GPIOA->CRL &= ~GPIO_CRL_MODE6;
    GPIOA->CRL |= GPIO_CRL_CNF6_0;
    GPIOA->CRL &= ~GPIO_CRL_CNF6_1;

/* 3、配置基本定时器TIM3 */
    /* 3.1、选择时钟源 */
    //默认为内部时钟源,所以无需代码配置

    /* 3.2、配置预分频PSC,分频系数为72 */
    TIM3->PSC = 72 - 1;//则一个脉冲的时间为1us

    /* 3.3、配置重装在值,为了防止溢出,配置最大*/
    TIM3->ARR = 65536 - 1;

    /* 3.4、配置计数器为向上计数:TIMx_CR1_DIR = 0 */
    TIM3->CR1 &= ~TIM_CR1_DIR;

/* 4、配置输入捕获相关寄存器 */
    /* 4.1、TIMx_CH1引脚连到TI1输入:TIMx_CR2_TI1S = 0 */
    TIM3->CR2 &= ~TIM_CR2_TI1S;

    /* 4.2、输入滤波器的配置,配置为不滤波:TIMx_CCMR1_IC1F = 0000 */
    TIM3->CCMR1 &= ~TIM_CCMR1_IC1F;

    /* 4.3、将CH1通道配置为输入捕获模式,且IC1映射到TI1:TIMx_CCMR1_CC1S = 01 
            将CH2通道配置为输入捕获模式,且IC2映射到TI1:TIMx_CCMR1_CC2S = 10*/
    TIM3->CCMR1 |= TIM_CCMR1_CC1S_0;
    TIM3->CCMR1 &= ~TIM_CCMR1_CC1S_1;//IC1映射在TI1FP1上
    TIM3->CCMR1 &= ~TIM_CCMR1_CC2S_0;
    TIM3->CCMR1 |= TIM_CCMR1_CC2S_1;//IC2映射在TI1上

    /* 4.5、配置IC1为捕获上升沿:TIMx_CCER_CC1P = 0 
            配置IC2为捕获下降沿:TIMx_CCER_CC2P = 0*/
    TIM3->CCER &= ~TIM_CCER_CC1P;
    TIM3->CCER |= TIM_CCER_CC2P;

    /* 4.6、输入捕获中IC1的预分频的配置(不分频):TIMx_CCMR1_IC1PSC = 00
            输入捕获中IC2的预分频的配置(不分频):TIMx_CCMR1_IC2PSC = 00 */
    TIM3->CCMR1 &= ~TIM_CCMR1_IC1PSC;
    TIM3->CCMR1 &= ~TIM_CCMR1_IC2PSC;

    /* 4.7、捕获/比较寄存器1使能:TIMx_CCER_CC1E = 1
            捕获/比较寄存器2使能:TIMx_CCER_CC2E = 1*/
    TIM3->CCER |= TIM_CCER_CC1E;
    TIM3->CCER |= TIM_CCER_CC2E;

/* 5、配置从模式 */
    /* 5.1、选择从模式的触发信号为TI1FP1:TIMx_SMCR_TS = 101 */
    TIM3->SMCR |= (TIM_SMCR_TS_0|TIM_SMCR_TS_2);
    TIM3->SMCR &= ~TIM_SMCR_TS_1;

    /* 5.2、配置从模式的工作模式:复位模式 TIMx_SMCR_SMS = 100 */
    TIM3->SMCR |= TIM_SMCR_SMS_2;
    TIM3->SMCR &= ~(TIM_SMCR_SMS_1|TIM_SMCR_SMS_0);

/* 6、使能计数器:TIMx_CR1_CEN = 1*/
    TIM3->CR1 |= TIM_CR1_CEN;
}

/**
 * 对将捕获/比较寄存器(CCR1)里面的值进行处理,获取PWM波形的周期(us)
 */
double Get_PWMCycle(void)
{
    return TIM3->CCR1;//返回为us
}

/**
 * 对将捕获/比较寄存器(CCR)里面的值进行处理,获取PWM波形的频率(Hz)
 */
 
double Get_PWMFrequency(void)
{
    return 1000000.0 / TIM3->CCR1;//返回为Hz
}

/**
 * 对将捕获/比较寄存器(CCR1)和(CCR2)里面的值进行处理,获取PWM波形占空比(%)
 */
double Get_PWMDutycycle(void)
{
    return ((TIM3->CCR2) * 100) / TIM3->CCR1;//返回为%
}

②TIM2.c文件的代码如下:

c 复制代码
#include "stm32f10x.h"                

/**
 * 通用定时器的输出比较模式输出PWM波形的初始化
 */
void TIM2_Init(void)
{
    /* 1、开启时钟 */
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;//开启GPIOA的时钟
    RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;//开启TIM2的时钟
    
    /* 2、配置GPIOA0(TIM2_CH1)引脚输出模式:复用推挽输出(MODE0 = 11,CNF0 = 10)*/
    GPIOA->CRL |= GPIO_CRL_MODE0;
    GPIOA->CRL &= ~GPIO_CRL_CNF0_0;
    GPIOA->CRL |= GPIO_CRL_CNF0_1;

    /* 3、定时器TIM2的配置 */
    /* 3.0、选择时钟源,默认的是内部时钟源ABP1*/
    
    /* 3.1、预分频器的设置 */
    TIM2->PSC = 7200 - 1;//每隔0.1ms来一个脉冲,计数一次

    /* 3.2、自动重装载寄存器的设置 */
    TIM2->ARR = 100 - 1;//一个周期的时间为10ms

    /* 3.3、计数器的计数方向:默认向上计数*/
    TIM2->CR1 &= ~TIM_CR1_DIR;//向上计数

    /* 4、配置输出比较 */
    /* 4.1、配置捕获比较寄存器的值 */
    TIM2->CCR1 = 50;

    /* 4.2、配置通道CH1的输出比较模式: TIMx_CCMR1_CC1S = 00(输出模式)
        TIMx_CCMR1_OC1M = 110(PWM1模式)
    */
    TIM2->CCMR1 &= ~TIM_CCMR1_CC1S;//CH1配置为输出模式
    TIM2->CCMR1 &= ~TIM_CCMR1_OC1M_0;
    TIM2->CCMR1 |= TIM_CCMR1_OC1M_1;
    TIM2->CCMR1 |= TIM_CCMR1_OC1M_2;

    /* 4.3、使能通道1:TIMx_CCER_CC1E = 1 */
    TIM2->CCER |= TIM_CCER_CC1E;//使能通道CH1

    /* 5、使能计数器 */
    TIM2->CR1 |= TIM_CR1_CEN;
}

/**
 * 更改占空比函数
 */
void Set_PWMDuty(uint8_t Data)
{
    TIM2->CCR1 = Data;
}

③主函数文件的代码如下:

c 复制代码
#include "stm32f10x.h"                
#include "TIM2.h"
#include "TIM3.h"
#include "OLED.h"
#include "Delay.h"

int main(void)
{ 
    uint8_t Data = 0;
    OLED_Init();
    OLED_ShowString(1,1,"Cycle:00000us");
    OLED_ShowString(2,1,"Freq:0000Hz");
    OLED_ShowString(3,1,"Duty:000%");

    TIM2_Init();//TIM2的初始化,产生了一个周期为10ms的PWM波形
    TIM3_Init();//TIM3的初始化,开启CH1输出捕获
    Set_PWMDuty(Data);
    
	while(1)
	{
       OLED_ShowNum(1,7,Get_PWMCycle(),5);
       OLED_ShowNum(2,6,Get_PWMFrequency(),4);
       OLED_ShowNum(3,6,Get_PWMDutycycle(),3);
        
       for(uint8_t i = 0; i<100; i++)
       {
           Set_PWMDuty(++Data);
           OLED_ShowNum(3,6,Get_PWMDutycycle(),3);//显示一下占空比
           Delay_ms(20);
       }
       for(uint8_t i = 0; i<100; i++)
       {
           Set_PWMDuty(--Data);
           OLED_ShowNum(3,6,Get_PWMDutycycle(),3);
           Delay_ms(20);
       }
	}
}

实物演示效果如下:

占空比

2、高级定时器

高级定时器有2个分别为TIM1和TIM8,而stm32f103c8t6只有一个高级定时器(TIM1)。高级定时器有通用定时器的所有功能外,还具备了以下的功能:
(1)重复计数器
(2)死区时间可编程的互补输出
(3)刹车输入信号

高级定时器的结构图如下:

如上图所示:①计数器CNT溢出1次时,重复计数器减1,当重复计数器溢出时(从0减到重复计数器的重装值),才会产生UI和U信号,若开启中断,才会执行中断。
重复计数器值为N,则CNT计数器溢出N+1次才会产生一次更新事件。

②死区时间可编程的互补输出:而互补输出一般情况下用于电机驱动,互补信号:频率周期相等,相位相差180°

③刹车输入信号:通过BKIN引脚输入/事件来控制定时器的比较输出。

高级定时器能产生中断的部位:

❄【注】①使用高级定时器的捕获/比较寄存器的通道输出波形,则要使能TIMx_BDTR_MOE位
②计数器使用的是向下计数+开启UP中断(计数器溢出中断),则在使能计数器前,将状态寄存器TIMx_SR_UIF位置0。否则一上电就会进入一次中断。(因为向下计数,初始前计数器里面的值为0,定时器初始化后,重装载寄存器里面的值会转载到计数器里面,计数器里面的值有0变为N,相当于一次溢出,产生一个更新事件,若开启了中断,则会立马进入中断复位函数)

相关推荐
gscsded1 小时前
C2000 GPIO 配置笔记
单片机
Sakuyu434681 小时前
STM32基础
stm32·单片机·嵌入式硬件
桑榆肖物1 小时前
ImprovWifi 跨平台传输层设计:把协议层做薄,把宿主层做稳
嵌入式硬件·wifi·.net·ble
gscsded1 小时前
C2000 CPU Timer 学习笔记
单片机
iCxhust3 小时前
AD0808调试笔记
笔记·单片机·嵌入式硬件·操作系统·微机原理·8088单板机
木子单片机3 小时前
基于51单片机的步进电机调速系统设计
单片机·嵌入式硬件·51单片机·keil
arronKler3 小时前
MySQL命令行导出数据库
c语言·数据库·mysql
三易串口屏4 小时前
实验10 物理按键实验
单片机·51单片机·串口屏·串口协议·uart 通信·嵌入式 ui
深圳光特通信豆子4 小时前
10Mb/s TTL单模双纤光收发模块技术规格手册
单片机·嵌入式硬件
潜创微科技4 小时前
IT6635+USB 芯片:4 进 1 出 4K@60Hz 高性能 KVM 切换器一站式方案
嵌入式硬件·音视频