0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

按这个步骤 STM32即可完美控制 NeoPixels

得捷电子DigiKey 来源:未知 2023-10-12 16:05 次阅读
Q A &

问:玩转STM32 - 使用 STM32 来控制 NeoPixels

目前,诸如ArduinoFeather等高级开发平台已经提供了出色的支持,可以通过易于使用的库和普遍使用的示例代码与NeoPixelLED灯带矩阵等相连接。然而,更高级的平台(例如STM32 开发板)通常缺乏相同水平的支持。因此,希望将NeoPixels整合到项目中的 开发人员需要全面了解NeoPixel通信协议以及如何克服它所带来的挑战。

wKgaomUt2iSAGmG6AATc_qP0mvo000.gif

NeoPixels

Adafruit推出的极受欢迎的可寻址全彩LED灯“NeoPixels”系列分为RGB和RGBW两个种类。尽管二者都将红、绿和蓝色LED与驱动器芯片相集成,但RGBW组件还集成了第四个纯白色的LED。可以使用类似的单线串行接口来控制这两种类型的NeoPixel,其时间值和数据结构仅存在微小的差异。

WS2812

RGB NeoPixels实际上是WS2812智能控制LED,包括数据信号输入引脚(DIN)和数据信号输出引脚(DOUT)。这允许多个LED级联并且只用一个数据线进行控制。链中的第一个LED负责处理从MCU接收到的前三个字节数据,然后将后续的数据简单地转发给DOUT引脚,该引脚可以连接到另一个LED的DIN引脚。LED将以此方式继续向下传递数据,直到它们接收到复位信号为止(即,DIN线在一段时间内持续保持低电平状态)。传输的字节按照图1所示的协议进行组织。第一个字节(G7-G0)表示绿色LED的8位PWM强度,其中0x00是完全关闭,0xFF是完全打开。类似地,第二个字节(R7-R0)用于控制红色LED的强度,第三个字节(B7-B0)用于控制蓝色LED的强度。

wKgaomUt2iWARBrUAAChoW2HPEQ727.png1WS2812 LED的3字节数据协议的结构这些24位数据都是通过改变方波的脉冲宽度来进行编码的,如图2所示。请注意,无论发送代码0还是代码1,方波的周期仍保持在1.25μs。对于WS2812,使数据线保持低电平至少50μs即可生成复位信号。另请注意,图2中显示的计时值具有±0.15μs的公差。

wKgaomUt2iWAY2DiAABEp1s2eiI317.png

图2:WS2812 LED的0和1位的计时图

一种截然不同的组件,NeoPixels的RGBW种类实际上是SK6812智能控制LED,采用与WS2812 LED相同的运作原理。然而,由于它们包含第四个LED,因此实施了图3所示的4字节数据协议。与图1相比,唯一的区别在于数据的串联字节(W7-W0),该字节指定了白色LED的8位PWM强度。

wKgaomUt2iWAWZ39AACfmWmMTtM004.png3SK6812 LED的4字节数据协议的结构。图4展示了SK6812控制信号的时间值,同样与WS2812略有差别(不过仍在±0.15μs的公差范围内)。请注意,这两种代码的方波周期均保持不变,都为1.2μs。此外,SK6812的复位信号长度为80μs,而非50μs。

wKgaomUt2iWAVVOiAABClficJjc287.png图4:SK6812 LED的0位和1位的计时图。

步骤

由于NeoPixel的控制信号对计时要求非常严格,因此除非使用汇编语言,否则无法通过简单的比特带宽方法产生此信号。虽然还有许多其他方法可以利用各种MCU外设、外部硬件或其组合来生成该信号,但其中最直接的方法是配置MCU定时器来生成PWM输出信号。这是因为,如上一部分中所述,NeoPixel控制信号只是一种固定频率的PWM信号,采用不同的占空比表示0位和1位。为了以与传输协议相同的速率高效地在这两个占空比之间进行切换,还必须配置DMA流来管理更新。尽管这种方法可能是内存效率最低的方式,但它易于理解、CPU高效并且易于实施(得益于STM32Cube环境)。

以下应用程式利用STM32CubeIDE(版本1.8.0)、NUCLEO-F401RE开发板和RGBW5x8 NeoPixel Shield实现上述的方法。不过,这些步骤可以轻松地推广到任何STM32MCU/板和NeoPixel产品上。假定我们已经创建了一个STM32CubeIDE项目。如需使用其他IDE,你可以改为使用独立的STM32CubeMX代码配置器工具,将项目导出到所需的开发平台上。

1.配置PWMa. 先打开STM32CubeMX配置.ioc文件(如果还未打开的话)。随后,STM32CubeIDE将切换到*器件配置工具(*Device Configuration Tool视图,供你配置MCU。

b. 将定时器通道备用功能分配给选定的GPIO引脚,以与NeoPixel进行连接。所选定时器通道应该能够生成PWM输出。图5显示了我的项目中的相关部分,我选择了引脚PB10,并将它分配给定时器2、通道3(TIM2_CH3)功能。

wKgaomUt2iWAVVSLAAJfdM6V1Qs446.png图5:将连接到DIN的GPIO引脚配置为定时器通道c. 从左侧的组件列表中选择上一步中确定的定时器外设,以打开模式和配置(*Mode andConfiguration面板。在模式(*Mode面板中,选择“内部时钟”作为时钟源,并从适当的定时器通道的下拉列表中选择“PWM生成CHx”。在图6中,定时器2、通道3已设为“PWM生成CH3”模式,因为我在上一步中选择了TIM2_CH3备用功能。请注意,在完成此步骤后,关联的GPIO引脚应在引脚排列视图中从黄色变为绿色。

d. 在定时器的*配置(*Configuration面板中,验证“预分频器”和“脉冲”值是否都设置为0。计数器周期,即自动重载寄存器(ARR),需要进行设置以得到所需的PWM周期(如果使用RGB WS2812 LED,则为1.25μs;如果使用RGBW SK6812 LED,则为1.2μs)。这将取决于定时器外设输入的速率。只需将所需的PWM周期除以时钟周期,并减去1即可得到此值(减去1是因为定数器从0开始)。就我的器件而言,该公式得出的ARR值为99.8,我将其四舍五入为100(图6)。请参见下文,了解有关计算理想ARR值的详细说明。

wKgaomUt2iaAOugvAAPcVg6siNg852.png图6:将所选定时器通道配置为PWM输出计算ARR值

假设定时器“预分频器”值设为0,可以很容易的计算出ARR值

wKgaomUt2iaAIheuAAAKT9ljiw4625.png具体来说,ARR值等于PWM信号周期除以定时器外设的时钟信号周期。我们知道,根据使用的NeoPixel类型不同,TPWM可以是1.25μs或1.2μs(例如本例中,TPWM=1.2μs)。要确定Ttimer,你需要查阅器件的规格书,确定定时器外设连接到哪个总线。规格书可以在ST的网站上找到或STM32CubeIDE会随附提供:选择帮助>目标器件文档和资源(Help>TargetDevice Docs and Resources。然后,在MCU选项卡下选择规格书,如图7所示。

wKgaomUt2iaAfEYGAADp-K-bUZI268.png7查找器件规格书

在我使用的MCU(STM32F401RE)规格书中,器件框图中显示我的定时器(TIM2)已连接到APB1(见图8)。

wKgaomUt2iaAP45cAAOisIZiqBU143.png8STM32F401xD/xE的部分框图(源自DS10086

图9介绍了:通过切换到STM32CubeIDE中的*时钟配置(*Clock Configuration)选项卡,我们可以发现TIM2的时钟频率为84MHzwKgaomUt2iaASHdtAAAJBaFQjxw634.png

wKgaomUt2iaAXwR4AAKKzg2YOko038.png

9确定定时器时钟频率

因此,wKgaomUt2iaAZ65gAAAJ-6pVqXY778.png为了使PWM周期尽可能接近NeoPixel控制信号的周期,我们四舍五入至最接近的整数并得到ARR=100。2.配置DMA

a. 从组件列表中选择DMA外设。

b. 在配置(Configuration)面板的DMA1选项卡下,点击添加Add按钮。在下拉菜单中,选择你的定时器/通道组合。在我的项目中,我选择了“TIM2_CH3/UP”。

c. 针对该新的DMA请求,将方向改为“内存到外设”。

d. 同时,将优先级改为“非常高”。

e. 验证默认的DMA请求设置是否与图10中显示的相匹配。

f. 保存.ioc文件,以生成项目代码。

wKgaomUt2ieADmNXAAIi9i5fDls339.png10配置DMA流,以便有效更新PWM信号的占空比

3.编写代码

在main.c文件中,按从上到下的顺序编写,本部分展示了一个简单的示例应用,用于测试NeoPixel LED的全彩能力。此处提供了两个版本的main()函数,一个用于RGB WS2818 LED,另一个用于RGBW SK6812 LED。

a. 在main.c文件的私有typedef部分,你可以创建一个新的数据类型,以便轻松访问单个LED颜色值以及整个NeoPixel数据结构(如图1和图3所示)。列表1提供了RGB和RGBW NeoPixel组件的typedef。此代码应粘贴在/* USER CODE BEGIN PTD */和/* USER CODE END PTD */注释之间。

列表1为RGB WS2812和RGBW SK6812 LED自定义数据类型

typedef union

{

struct

{

uint8_t b;

uint8_t r;

uint8_t g;

} color;

uint32_t data;

} PixelRGB_t;

typedef union

{

struct

{

uint8_t w;

uint8_t b;

uint8_t r;

uint8_t g;

} color;

uint32_t data;

} PixelRGBW_t;

b. 更改“脉冲”寄存器(也称为CCRx)的值,这样可以改变PWM波形的占空比。因此,我们必须计算适当的CCRx值,以实现使用的NeoPixels所需的代码0和代码1方波(无论是在图2还是图4中所示的那些)。对于RGBWS2812 LED,这些值计算如下:

ZERO=(ARR+1)(0.32)

ONE=(ARR+1)(0.64)

对于RGBW SK6812 LED,其计算过程稍有不同。

ZERO=(ARR+1)(0.25)

ONE=(ARR+1)(0.5)

当然,这些计算出的值应该四舍五入到最接近的整数。在main.c文件的私有定义部分,为每个值创建一个#define指令(请参见以下图11中的示例)。

c. 除了CCRx值之外,还应在私有定义部分中定义控制的NeoPixel LED数量和DMA缓冲区大小。如图11所示,只需将LED的数量乘以相应的NeoPixel数据结构中的位数即可(回想图1和图3)。还必须分配一个额外的缓冲区元素,因为最后一个CCRx值应为零(复位信号)。

wKgaomUt2ieAQ_4iAAJKl2kCKjk144.png11WS2812和SK6812LED的私有定义

d. 将列表2中提供的DMA完成回调函数添加到/* USER CODE BEGIN 0/和/USER CODE END 0*/之间的私有用户代码部分。务必将TIM_CHANNEL_x更改为步骤1c中配置的通道。

列表2HAL_TIM_PWM_PulseFinishedCallback()函数的实施

void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)

{

HAL_TIM_PWM_Stop_DMA(htim, TIM_CHANNEL_x);

}

e. 最后,必须将应用代码添加到main()函数中。列表3提供了一个使用WS2812LED的示例main()函数,而列表4提供了使用SK6812 LED的类似示例main()函数。请注意,HAL_TIM_PWM_Start_DMA()函数的TIM_CHANNEL_x参数必须再次进行修改,以匹配步骤1c中配置的通道。

列表3RGB WS2812 LED的示例main()函数

int main(void)

{

/* USER CODE BEGIN 1 */

PixelRGB_tpixel[NUM_PIXELS] = {0};

uint32_tdmaBuffer[DMA_BUFF_SIZE] = {0};

uint32_t *pBuff;

int i, j, k;

uint16_t stepSize;

/* USER CODE END 1 */

/* MCUConfiguration--------------------------------------------------------*/

/* Reset of allperipherals, Initializes the Flash interface and the Systick. */

HAL_Init();

/* USER CODE BEGIN Init*/

/* USER CODE END Init*/

/* Configure the systemclock */

SystemClock_Config();

/* USER CODE BEGINSysInit */

/* USER CODE ENDSysInit */

/* Initialize allconfigured peripherals */

MX_GPIO_Init();

MX_USART2_UART_Init();

MX_DMA_Init();

MX_TIM2_Init();

/* USER CODE BEGIN 2 */

/* USER CODE END 2 */

/* Infinite loop */

/* USER CODE BEGINWHILE */

k = 0;

stepSize = 4;

while (1)

{

/* USER CODE ENDWHILE */

/* USER CODE BEGIN 3*/

for (i = (NUM_PIXELS- 1); i > 0; i--)

{

pixel[i].data =pixel[i-1].data;

}

if (k < 255)

{

pixel[0].color.g =254 - k; //[254, 0]

pixel[0].color.r= k + 1; //[1, 255]

pixel[0].color.b =0;

}

else if (k < 510)

{

pixel[0].color.g =0;

pixel[0].color.r =509 - k; //[254, 0]

pixel[0].color.b =k - 254; //[1, 255]

j++;

}

else if (k < 765)

{

pixel[0].color.g =k - 509; //[1, 255];

pixel[0].color.r =0;

pixel[0].color.b =764 - k; //[254, 0]

}

k = (k + stepSize) %765;

// not so bright

pixel[0].color.g>>= 2;

pixel[0].color.r>>= 2;

pixel[0].color.b>>= 2;

pBuff = dmaBuffer;

for (i = 0; i

{

for (j = 23; j>= 0; j--)

{

if((pixel[i].data >> j) & 0x01)

{

*pBuff =NEOPIXEL_ONE;

}

else

{

*pBuff =NEOPIXEL_ZERO;

}

pBuff++;

}

}

dmaBuffer[DMA_BUFF_SIZE - 1] = 0; // last element must be 0!

HAL_TIM_PWM_Start_DMA(&htim2, TIM_CHANNEL_x, dmaBuffer,DMA_BUFF_SIZE);

HAL_Delay(10);

}

/* USER CODE END 3 */

}

列表4RGBW SK6812 LED的示例main()函数

int main(void)

{

/* USER CODE BEGIN 1 */

PixelRGBW_tpixel[NUM_PIXELS] = {0};

uint32_tdmaBuffer[DMA_BUFF_SIZE] = {0};

uint32_t *pBuff;

int i, j, k;

uint16_t stepSize;

/* USER CODE END 1 */

/* MCU Configuration--------------------------------------------------------*/

/* Reset of allperipherals, Initializes the Flash interface and the Systick. */

HAL_Init();

/* USER CODE BEGIN Init*/

/* USER CODE END Init*/

/* Configure the systemclock */

SystemClock_Config();

/* USER CODE BEGINSysInit */

/* USER CODE ENDSysInit */

/* Initialize allconfigured peripherals */

MX_GPIO_Init();

MX_USART2_UART_Init();

MX_DMA_Init();

MX_TIM2_Init();

/* USER CODE BEGIN 2 */

/* USER CODE END 2 */

/* Infinite loop */

/* USER CODE BEGINWHILE */

k = 0;

stepSize = 4;

while (1)

{

/* USER CODE ENDWHILE */

/* USER CODE BEGIN 3*/

for (i = (NUM_PIXELS- 1); i > 0; i--)

{

pixel[i].data =pixel[i-1].data;

}

if (k < 255)

{

pixel[0].color.g =254 - k; //[254, 0]

pixel[0].color.r= k + 1;//[1, 255]

pixel[0].color.b =0;

pixel[0].color.w =0;

}

else if (k < 510)

{

pixel[0].color.g =0;

pixel[0].color.r =509 - k; //[254, 0]

pixel[0].color.b =k - 254; //[1, 255]

pixel[0].color.w =0;

j++;

}

else if (k < 765)

{

pixel[0].color.g =0;

pixel[0].color.r =0;

pixel[0].color.b =764 - k; //[254, 0]

pixel[0].color.w =k - 509; //[1, 255]

}

else if (k < 1020)

{

pixel[0].color.g =k - 764; //[1, 255]

pixel[0].color.r =0;

pixel[0].color.b =0;

pixel[0].color.w =1019 - k; //[254, 0]

}

k = (k + stepSize) %1020;

// 50% brightness

pixel[0].color.g>>= 2;

pixel[0].color.r>>= 2;

pixel[0].color.b>>= 2;

pixel[0].color.w>>= 2;

pBuff = dmaBuffer;

for (i = 0; i

{

for (j = 31; j>= 0; j--)

{

if((pixel[i].data >> j) & 0x01)

{

*pBuff =NEOPIXEL_ONE;

}

else

{

*pBuff =NEOPIXEL_ZERO;

}

pBuff++;

}

}

dmaBuffer[DMA_BUFF_SIZE- 1] = 0; // last element must be 0!

HAL_TIM_PWM_Start_DMA(&htim2, TIM_CHANNEL_x, dmaBuffer,DMA_BUFF_SIZE);

HAL_Delay(10);

}

/* USER CODE END 3 */

}

该项目现在应该能够成功构建,并支持你在器件上运行代码了。

结论

使用逻辑分析仪捕获了上面提供的RGB和RGBW配置生成的控制信号。分别如图12和图13中所示。请注意,它们与图2和图4中指定的预期输出相匹配。

wKgaomUt2ieAcksKAAEm1bEMPC4910.png

12生成的WS2812控制信号(正在发送0b0011……)

wKgaomUt2ieAcYyWAAEI1x0Mck0349.png

13生成的SK6812控制信号(正在发送0b0010……)

wKgaomUt2ieAZduiAAABcngP-W4089.png

更多STM32项目的相关内容请查看以下帖子:
  • 在STM32上轻松使用printf函数

  • 在STM32上轻松使用scanf

  • 轻松在 STM32 系列之间进行迁移

  • 利用 STM32CubeIDE 中构建分析仪

  • VL53L5CXToF传感器使用入门
wKgaomUt2ieAZduiAAABcngP-W4089.png    最后,如果你喜欢这篇文章,快分享给更多的小伙伴吧!切记点个赞哦!

提示点击菜单设计支持:工程师锦囊,获取更多工程师小贴士

秘技知识学不停 专属福利享不停

就等您加入!

点此登记

赚积分、换好礼

立即到「会员权益」查看您的礼遇! 如有任何问题,欢迎联系得捷电子DigiKey的客服团队

中国(人民币)客服

wKgaomUt2iiAeQBCAAADBaTNctA462.png400-920-1199wKgaomUt2iiAB_4FAAADAQryhLs505.png服务支持 > 联系客服 > 微信客服wKgaomUt2iiALRPpAAADNUSMvSY112.pngservice.sh@digikey.comwKgaomUt2iiATrlcAAACyRJDcPk162.png QQ在线实时咨询:4009201199

中国(美金)/ 香港客服

wKgaomUt2iiAeQBCAAADBaTNctA462.png

400-882-4440

wKgaomUt2iiAeQBCAAADBaTNctA462.png852-3104-0500wKgaomUt2iiALRPpAAADNUSMvSY112.pngchina.support@digikey.comwKgaomUt2iiAZleMAACA1g3d7HM828.png

wKgaomUt2iiAeytWAAJQEo9UZ9g629.png

点击下方“阅读原文”查看更多

让我知道你在看wKgaomUt2iiAfDHdAAAD385SHbk261.png


原文标题:按这个步骤 STM32即可完美控制 NeoPixels

文章出处:【微信公众号:得捷电子DigiKey】欢迎添加关注!文章转载请注明出处。


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 得捷电子
    +关注

    关注

    1

    文章

    255

    浏览量

    8771

原文标题:按这个步骤 STM32即可完美控制 NeoPixels

文章出处:【微信号:得捷电子DigiKey,微信公众号:得捷电子DigiKey】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    湿法刻蚀步骤有哪些

    说到湿法刻蚀了,这个是专业的技术。我们也得用专业的内容才能给大家讲解。听到这个工艺的话,最专业的一定就是讲述湿法刻蚀步骤。你知道其中都有哪些步骤吗?如果想要了解,今天是一个不错的机会,
    的头像 发表于 12-13 14:08 64次阅读

    stm32 GPIO中断配置教程

    理解GPIO中断 在STM32中,GPIO中断允许微控制器在引脚状态变化时(如从低到高或从高到低)立即响应,而无需不断轮询引脚状态。这对于处理外部事件(如按钮下、传感器信号等)非常有用。 2. 硬件准备
    的头像 发表于 11-19 15:53 659次阅读

    LMK05318手册里的编写EEPROM的步骤这个掩码什么意思?

    如下图所示,是LMK05318手册里的编写EEPROM的步骤,没看懂这个掩码什么意思 然后,我在调试过程中发现几个问题: 1.在编写程序时,如果不执行第三步,烧录后发现程序能出来正常波形,否则
    发表于 11-11 08:14

    STM32项目实战:基于STM32U5的智能灯光控制系统(LVGL),附项目教程/源码

    《智能灯光控制系统_STM32U5》项目完整文档、项目源码,点击免费领取。项目资料领取:https://s.c1ns.cn/F5XyUSTM32项目实战之“智能灯光控制系统”(基于
    的头像 发表于 11-07 18:50 751次阅读
    <b class='flag-5'>STM32</b>项目实战:基于<b class='flag-5'>STM32</b>U5的智能灯光<b class='flag-5'>控制</b>系统(LVGL),附项目教程/源码

    STM32项目实战:基于STM32F4的智能灯光控制系统(LVGL),附项目教程/源码

    《智能灯光控制系统_STM32F4》项目完整文档、项目源码,私信小雯老师免费领取。STM32项目实战之“智能灯光控制系统”(基于STM32F
    的头像 发表于 10-17 16:16 751次阅读
    <b class='flag-5'>STM32</b>项目实战:基于<b class='flag-5'>STM32</b>F4的智能灯光<b class='flag-5'>控制</b>系统(LVGL),附项目教程/源码

    电气控制线路的安装步骤和注意事项

    在电气工程领域,控制线路的安装是确保电气系统正常运行的关键步骤。为了实现高效且安全的安装过程,以下是一系列详尽的步骤和注意事项: 理解原理图:在开始任何实际工作之前,彻底理解原理图是必不可少
    的头像 发表于 09-30 15:30 545次阅读

    stm32g与stm32h的区别

    STM32G和STM32H是STMicroelectronics(意法半导体)推出的两个不同的微控制器系列,它们都属于STM32的广泛产品线。STM
    的头像 发表于 09-04 09:15 704次阅读

    bin文件怎么烧录到stm32

    号的STM32开发板,如STM32F103、STM32F407等。选择适合自己需求的开发板即可。 USB数据线 烧录STM32
    的头像 发表于 08-22 09:38 1898次阅读

    组合逻辑控制器的设计步骤是什么

    于计算机、通信、控制等领域。本文将详细介绍组合逻辑控制器的设计步骤,包括需求分析、逻辑功能定义、逻辑表达式、逻辑图、电路设计、仿真验证、测试和优化等。 需求分析 需求分析是设计组合逻辑控制
    的头像 发表于 06-30 10:30 706次阅读

    全自动绝缘油耐压测试仪的操作步骤——每日了解电力知识

    ) 2.在图1页面下, 设置 键进入下一级页面(图2); 3.在图2页面下, 选择 键移动光标√ 至 GB1986处, 确认 键即可进入国标1986设置子页面(图3)。 在图3页
    的头像 发表于 06-17 10:23 550次阅读
    全自动绝缘油耐压测试仪的操作<b class='flag-5'>步骤</b>——每日了解电力知识

    stm32f303工程的步骤是什么?

    求大神指导:建一个stm32f303工程,本人只下载了keil5软件,还需要下载什么,下载之后的建工程步骤是什么?
    发表于 04-11 07:07

    按钮控制电机正反转电路分析

    红色为带电部分。这个电路的动作步骤是:第一次SB,KM1吸合,正转启动,第二次SB,KM1释放,电机停止。第三次SB,KM2吸合,反转
    发表于 03-31 16:47 2956次阅读
    按钮<b class='flag-5'>控制</b>电机正反转电路分析

    STM32电机控制SDK v5.0入门

    电子发烧友网站提供《STM32电机控制SDK v5.0入门.pdf》资料免费下载
    发表于 03-11 09:25 10次下载

    plc控制系统的设计步骤有哪些

    PLC控制系统设计是一个非常复杂的过程,下面介绍PLC控制系统设计步骤。 第一步:明确需求 在设计PLC控制系统之前,首先需要明确需求。这包括确定
    的头像 发表于 01-16 16:21 3335次阅读

    stm32使用AD5762配置程序

    AD5762是一款由ADI(Analog Devices)推出的12位单通道、高速、低功耗的数字模拟转换器(DAC)。它是STM32控制器的一部分,用于实现模拟输出功能。本文将详细介绍
    的头像 发表于 01-09 11:10 697次阅读