侵权投诉

浅谈嵌入式中的C语言编程技术分析

FPGA那点事儿 ? 2021-08-19 14:50 ? 次阅读

嵌入式产品的可靠性自然与硬件密不可分,但在硬件确定、并且没有第三方测试的前提下,使用防御性编程思想写出的代码,往往具有更高的稳定性。

防御性编程首先需要认清C语言的种种缺陷和陷阱,C语言对于运行时的检查十分弱小,需要程序员谨慎的考虑代码,在必要的时候增加判断;防御性编程的另一个核心思想是假设代码运行在并不可靠的硬件上,外接干扰有可能会打乱程序执行顺序、更改RAM存储数据等等。

1具有形参的函数,需判断传递来的实参是否合法

程序员可能无意识的传递了错误参数;外界的强干扰可能将传递的参数修改掉,或者使用随机参数意外的调用函数,因此在执行函数主体前,需要先确定实参是否合法。

4c99c0fa-fd3c-11eb-9bcf-12bb97331649.png

2仔细检查函数的返回值

对函数返回的错误码,要进行全面仔细处理,必要时做错误记录。

4ca27a06-fd3c-11eb-9bcf-12bb97331649.png

3防止指针越界

如果动态计算一个地址时,要保证被计算的地址是合理的并指向某个有意义的地方。特别对于指向一个结构或数组的内部的指针,当指针增加或者改变后仍然指向同一个结构或数组。

4防止数组越界

数组越界的问题前文已经讲述的很多了,由于C不会对数组进行有效的检测,因此必须在应用中显式的检测数组越界问题。下面的例子可用于中断接收通讯数据。

4cbb786c-fd3c-11eb-9bcf-12bb97331649.png

在使用一些库函数时,同样需要对边界进行检查,比如下面的memset(RecBuf,0,len)函数把RecBuf指指向的内存区的前len个字节用0填充,如果不注意len的长度,就会将数组RecBuf之外的内存区清零:

4ce8cf2e-fd3c-11eb-9bcf-12bb97331649.png

5数学数运算

5.1除法运算,只检测除数为零就可靠吗?

除法运算前,检查除数是否为零几乎已经成为共识,但是仅检查除数是否为零就够了吗?

考虑两个整数相除,对于一个signed long类型变量,它能表示的数值范围为:-2147483648 ~+2147483647,如果让-2147483648/ -1,那么结果应该是+2147483648,但是这个结果已经超出了signedlong所能表示的范围了。所以,在这种情况下,除了要检测除数是否为零外,还要检测除法是否溢出。

 #include <limits.h>  
   signed long sl1,sl2,result; /*初始化sl1和sl2*/   
  if((sl2==0)||(sl1==LONG_MIN && sl2==-1)) {  
   //处理错误     } else  
  {     result = sl1 / sl2; }

5.2检测运算溢出

整数的加减乘运算都有可能发生溢出,在讨论未定义行为时,给出过一个有符号整形加法溢出判断代码,这里再给出一个无符号整形加法溢出判断代码段:

 #include      unsigned int a,b,result; /*初始化a,b*/     if(UINT_MAX-a {     //处理溢出     } else    {     result=a+b; }

嵌入式硬件一般没有浮点处理器,浮点数运算在嵌入式也比较少见并且溢出判断严重依赖C库支持,这里不讨论。

5.3检测移

在讨论未定义行为时,提到有符号数右移、移位的数量是负值或者大于操作数的位数都是未定义行为,也提到不对有符号数进行位操作,但要检测移位的数量是否大于操作数的位数。下面给出一个无符号整数左移检测代码段:

 unsigned int ui1; unsigned int ui2; unsigned int uresult; /*初始化ui1,ui2*/   if(ui2>=sizeof(unsigned int)*CHAR_BIT) {     //处理错误   } else   {     uresult=ui1< }

6如果有硬件看门狗,则使用它

在其它一切措施都失效的情况下,看门狗可能是最后的防线。它的原理特别简单,但却能大大提高设备的可靠性。如果设备有硬件看门狗,一定要为它编写驱动程序。

  • 要尽可能早的开启看门狗

这是因为从上电复位结束到开启看门狗的这段时间内,设备有可能被干扰而跳过看门狗初始化程序,导致看门狗失效。尽可能早的开启看门狗,可以降低这种概率;

  • 不要在中断中喂狗,除非有其他联动措施

在中断程序喂狗,由于干扰的存在,程序可能一直处于中断之中,这样会导致看门狗失效。如果在主程序中设置标志位,中断程序喂狗时与这个标志位联合判断,也是允许的;

  • 喂狗间隔跟产品需求有关,并非特定的时间

产品的特性决定了喂狗间隔。对于不涉及安全性、实时性的设备,喂狗间隔比较宽松,但间隔时间不宜过长,否则被用户感知到,是影响用户体验的。对于设计安全性、有实时控制类的设备,原则是尽可能快的复位,否则会造成事故。

克莱门汀号在进行第二阶段的任务时,原本预订要从月球飞行到太空深处的Geographos小行星进行探勘,然而这艘太空探测器在飞向小行星时却由于一个软件缺陷而使其中断运作20分钟,不但未能到达小行星,也因为控制喷嘴燃烧了11分钟使电力供应降低,无法再透过远端控制探测器,最终结束这项任务,但也导致了资源与资金的浪费。

“克莱门汀太空任务失败这件事让我感到十分震惊,它其实可以透过硬件中一款简单的看门狗计时器避免掉这项意外,但由于当时的开发时间相当紧缩,程序设计人员没时间编写程序来启动它,”Ganssle说。

遗憾的是,1998年发射的近地号太空船(NEAR)也遇到了相同的问题。由于编程人员并未采纳建议,因此,当推进器减速器系统故障时,29公斤的储备燃料也随之报销──这同样是一个本来可经由看门狗定时器编程而避免的问题,同时也证明要从其他程序设计人员的错误中学习并不容易。

7 关键数据储存多个备份,取数据采用“表决法”

RAM中的数据在受到干扰情况下有可能被改变,对于系统关键数据应该进行保护。关键数据包括全局变量、静态变量以及需要保护的数据区域。备份数据与原数据不应该处于相邻位置,因此不应由编译器默认分配备份数据位置,而应该由程序员指定区域存储。

可以将RAM分为3个区域,第一个区域保存原码,第二个区域保存反码,第三个区域保存异或码,区域之间预留一定量的“空白”RAM作为隔离。可以使用编译器的“分散加载”机制将变量分别存储在这些区域。需要进行读取时,同时读出3份数据并进行表决,取至少有两个相同的那个值。

假如设备的RAM从0x1000_0000开始,我需要在RAM的0x1000_0000~0x10007FFF内存储原码,在0x1000_9000~0x10009FFF内存储反码,在0x1000_B000~0x1000BFFF内存储0xAA的异或码,编译器的分散加载可以设置为:

 LR_IROM1 0x00000000 0x00080000  {   
 ; load region size_region
ER_IROM10x000000000x00080000
{;loadaddress=execution address  
  *.o (RESET, +First)    *(InRoot$$Sections)   
 .ANY (+RO)   }   RW_IRAM1 0x10000000 0x00008000
  {  ;保存原码    .ANY (+RW +ZI )  
 }   RW_IRAM3 0x10009000 0x00001000{
    ;保存反码    .ANY (MY_BK1)  
 }   RW_IRAM2 0x1000B000 0x00001000  
{  ;保存异或码    .ANY (MY_BK2)  
 } }

如果一个关键变量需要多处备份,可以按照下面方式定义变量,将三个变量分别指定到三个不连续的RAM区中,并在定义时按照原码、反码、0xAA的异或码进行初始化。

 uint32  plc_pc=0;                                                       //原码   __attribute__((section("MY_BK1"))) uint32 plc_pc_not=~0x0;              //反码   __attribute__((section("MY_BK2"))) uint32 plc_pc_xor=0x0^0xAAAAAAAA;    //异或码

当需要写这个变量时,这三个位置都要更新;读取变量时,读取三个值做判断,取至少有两个相同的那个值。

为什么选取异或码而不是补码?这是因为MDK的整数是按照补码存储的,正数的补码与原码相同,在这种情况下,原码和补码是一致的,不但起不到冗余作用,反而对可靠性有害。比如存储的一个非零整数区因为干扰,RAM都被清零,由于原码和补码一致,按照3取2的“表决法”,会将干扰值0当做正确的数据。

8 对非易失性存储器进行备份存

非易失性存储器包括但不限于Flash、EEPROM、铁电。仅仅将写入非易失性存储器中的数据再读出校验是不够的。强干扰情况下可能导致非易失性存储器内的数据错误,在写非易失性存储器的期间系统掉电将导致数据丢失,因干扰导致程序跑飞到写非易失性存储器函数中,将导致数据存储紊乱。

一种可靠的办法是将非易失性存储器分成多个区,每个数据都将按照不同的形式写入到这些分区中,需要进行读取时,同时读出多份数据并进行表决,取相同数目较多的那个值。

9 软件

对于初始化序列或者有一定先后顺序的函数调用,为了保证调用顺序或者确保每个函数都被调用,我们可以使用环环相扣,实质上这也是一种软件锁。此外对于一些安全关键代码语句(是语句,而不是函数),可以给它们设置软件锁,只有持有特定钥匙的,才可以访问这些关键代码。也可以通俗的理解为,关键安全代码不能按照单一条件执行,要额外的多设置一个标志。

比如,向Flash写一个数据,我们会判断数据是否合法、写入的地址是否合法,计算要写入的扇区。之后调用写Flash子程序,在这个子程序中,判断扇区地址是否合法、数据长度是否合法,之后就要将数据写入Flash。

由于写Flash语句是安全关键代码,所以程序给这些语句上锁:必须具有正确的钥匙才可以写Flash。这样即使是程序跑飞到写Flash子程序,也能大大降低误写的风险。

  • * 名称:RamToFlash() * 功能:复制RAM的数据到FLASH,命令代码51。
  • * 入口参数:dst 目标地址,即FLASH起始地址。以512字节为分界
  • * src 源地址,即RAM地址。地址必须字对齐 * no 复制字节个数,为512/1024/4096/8192 * ProgStart 软件锁标志 * 出口参数:IAP返回值(paramout缓冲区) CMD_SUCCESS,SRC_ADDR_ERROR,DST_ADDR_ERROR, SRC_ADDR_NOT_MAPPED,DST_ADDR_NOT_MAPPED,COUNT_ERROR,BUSY,未选择扇区 ****************************************************************/
  • void RamToFlash(uint32 dst, uint32 src, uint32 no,uint8 ProgStart)
  • { PLC_ASSERT("Sector number",(dst>=0x00040000)&&(dst<=0x0007FFFF)); PLC_ASSERT("Copy bytes number is 512",(no==512)); PLC_ASSERT("ProgStart==0xA5",(ProgStart==0xA5)); paramin[0] = IAP_RAMTOFLASH; // 设置命令字 paramin[1] = dst; // 设置参数 paramin[2] = src; paramin[3] = no; paramin[4] = Fcclk/1000;
  • if(ProgStart==0xA5)
  • //只有软件锁标志正确时,才执行关键代码
  • { iap_entry(paramin, paramout); // 调用IAP服务程序 ProgStart=0; } else { paramout[0]=PROG_UNSTART; } }

该程序段是编程lpc1778内部Flash,其中调用IAP程序的函数iap_entry(paramin, paramout)是关键安全代码,所以在执行该代码前,先判断一个特定设置的安全锁标志ProgStart,只有这个标志符合设定值,才会执行编程Flash操作。如果因为意外程序跑飞到该函数,由于ProgStart标志不正确,是不会对Flash进行编程的。

10 通信

通讯线上的数据误码相对严重,通讯线越长,所处的环境越恶劣,误码会越严重。抛开硬件和环境的作用,我们的软件应能识别错误的通讯数据。对此有一些应用措施:

  • 制定协议时,限制每帧的字节数;

每帧字节数越多,发生误码的可能性就越大,无效的数据也会越多。对此以太网规定每帧数据不大于1500字节,高可靠性的CAN收发器规定每帧数据不得多于8字节,对于RS485,基于RS485链路应用最广泛的Modbus协议一帧数据规定不超过256字节。因此,建议制定内部通讯协议时,使用RS485时规定每帧数据不超过256字节;

  • 使用多种校验

编写程序时应使能奇偶校验,每帧超过16字节的应用,建议至少编写CRC16校验程序。

  • 增加额外判断

1)增加缓冲区溢出判断。这是因为数据接收多是在中断中完成,编译器检测不出缓冲区是否溢出,需要手动检查,在上文介绍数据溢出一节中已经详细说明。

2)增加超时判断。当一帧数据接收到一半,长时间接收不到剩余数据,则认为这帧数据无效,重新开始接收。可选,跟不同的协议有关,但缓冲区溢出判断必须实现。这是因为对于需要帧头判断的协议,上位机可能发送完帧头后突然断电,重启后上位机是从新的帧开始发送的,但是下位机已经接收到了上次未发送完的帧头,所以上位机的这次帧头会被下位机当成正常数据接收。这有可能造成数据长度字段为一个很大的值,填满该长度的缓冲区需要相当多的数据(比如一帧可能1000字节),影响响应时间;另一方面,如果程序没有缓冲区溢出判断,那么缓冲区很可能溢出,后果是灾难性的。

  • 重传机制

如果检测到通讯数据发生了错误,则要有重传机制重新发送出错的帧。

11 开关量输入的检测、确认

开关量容易受到尖脉冲干扰,如果不进行滤除,可能会造成误动作。一般情况下,需要对开关量输入信号进行多次采样,并进行逻辑判断直到确认信号无误为止。

12 开关量输出

开关信号简单的一次输出是不安全的,干扰信号可能会翻转开关量输出的状态。采取重复刷新输出可以有效防止电平的翻转。

13 初始化信息的保存和恢复

微处理器的寄存器值也可能会因外界干扰而改变,外设初始化值需要在寄存器中长期保存,最容易被破坏。由于Flash中的数据相对不易被破坏,可以将初始化信息预先写入Flash,待程序空闲时比较与初始化相关的寄存器值是否被更改,如果发现非法更改则使用Flash中的值进行恢复。

公司目前使用的4.3寸LCD显示屏抗干扰能力一般。如果显示屏与控制器之间的排线距离过长或者对使用该显示屏的设备打静电或者脉冲群,显示屏有可能会花屏或者白屏。

对此,我们可以将初始化显示屏的数据保存在Flash中,程序运行后,每隔一段时间从显示屏的寄存器读出当前值和Flash存储的值相比较,如果发现两者不同,则重新初始化显示屏。下面给出校验源码,仅供参考。

定义数据结构:

4d0349b2-fd3c-11eb-9bcf-12bb97331649.png

定义const修饰的结构体变量,存储LCD部分寄存器的初始值,这个初始值跟具体的应用初始化有关,不一定是表中的数据,通常情况下,这个结构体变量被存储到Flash中。

 /*LCD部分寄存器设置值列表*/  
 lcd_redu_list_struct const lcd_redu_list_str[]= { 

  {SSD1963_Get_Address_Mode,{0x20}                                  
 ,1}, /*1*/    {SSD1963_Get_Pll_Mn      
,{0x3b,0x02,0x04}                      
   ,3}, /*2*/   
 {SSD1963_Get_Pll_Status 
 ,{0x04}                              
     ,1}, /*3*/   
 {SSD1963_Get_Lcd_Mode  
  ,{0x24,0x20,0x01,0xdf,0x01,0x0f,0x00}    
 ,7}, /*4*/   
 {SSD1963_Get_Hori_Period ,{0x02,0x0c,0x00,0x2a,0x07,0x00,0x00,0x00},8}, /*5*/  
  {SSD1963_Get_Vert_Period ,{0x01,0x1d,0x00,0x0b,0x09,0x00,0x00}    
 ,7}, /*6*/    {SSD1963_Get_Power_Mode  ,{0x1c}                                  
 ,1}, /*7*/    {SSD1963_Get_Display_Mode,{0x03}                                 
  ,1}, /*8*/    {SSD1963_Get_Gpio_Conf   ,{0x0F,0x01}                       
       ,2}, /*9*/   
 {SSD1963_Get_Lshift_Freq ,{0x00,0xb8}                         
     ,2}, /*10*/ };

实现函数如下所示,函数会遍历结构体变量中的每一个命令,以及每一个命令下的初始值,如果有一个不正确,则跳出循环,执行重新初始化和恢复措施。这个函数中的MY_DEBUGF宏是我自己的调试函数,使用串口打印调试信息,在接下来的第五部分将详细叙述。

通过这个函数,我可以长时间监控显示屏的哪些命令、哪些位容易被干扰。程序里使用了一个被妖魔化的关键字:goto。大多数C语言书籍对goto关键字谈之色变,但你应该有自己的判断。在函数内部跳出多重循环,除了goto关键字,又有哪种方法能如此简洁高效!

 /**  * lcd 显示冗余  * 每隔一段时间调用该程序一次  */  
 void lcd_redu(void)   {  
   uint8_t  tmp[8];   
  uint32_t i,j;   
  uint32_t lcd_init_flag;   
  lcd_init_flag =0;
for(i=0;i<sizeof(lcd_redu_list_str)/sizeof(lcd_redu_list_str[0]);i+)     
{         LCD_SendCommand(lcd_redu_list_str[i].lcd_command);         
uyDelay(10);     
    for(j=0;j<lcd_redu_list_str[i].lcd_value_num;j++)     
    {             tmp[j]=LCD_ReadData();       
      if(tmp[j]!=lcd_redu_list_str[i].lcd_get_value[j])       
      {                 lcd_init_flag=0x55;                
 MY_DEBUGF(MENU_DEBUG,("读lcd寄存器值与预期不符,命令为:0x%x,第%d个参数,          
   该参数正确值为:0x%x,实际读出值为:0x%xn",lcd_redu_list_str[i].lcd_command,j+1,       
      lcd_redu_list_str[i].lcd_get_value[j],tmp[j]));                
 goto handle_lcd_init;             }         }     } 
    handle_lcd_init:  
   if(lcd_init_flag==0x55)   
  {         //重新初始化LCD        
   //一些必要的恢复措施       } }

14 陷阱


对于8051内核单片机,由于没有相应的硬件支持,可以用纯软件设置软件陷阱,用来拦截一些程序跑飞。对于ARM7或者Cortex-M系列单片机,硬件已经内建了多种异常,软件需要根据硬件异常来编写陷阱程序,用来快速定位甚至恢复错误。

15 阻塞处理

有时候程序员会使用while(!flag);语句阻塞在此等待标志flag改变,比如串口发送时用来等待一字节数据发送完成。这样的代码时存在风险的,如果因为某些原因标志位一直不改变则会造成系统死机。

一个良好冗余的程序是设置一个超时定时器,超过一定时间后,强制程序退出while循环。

2003年8月11日发生的W32.Blaster.Worm蠕虫事件导致全球经济损失高达5亿美元,这个漏洞是利用了Windows分布式组件对象模型的远程过程调用接口中的一个逻辑缺陷:在调用GetMachineName()函数时,循环只设置了一个不充分的结束条件。

原代码简化如下所示:

4d20a930-fd3c-11eb-9bcf-12bb97331649.png

软发布的安全补丁MS03-026解决了这个问题,为GetMachineName()函数设置了充分终止条件。一个解决代码简化如下所示(并非微软补丁代码):

 HRESULT GetMachineName( WCHAR *pwszPath,
   WCHARwszMachineName[MAX_COMPUTTERNAME_LENGTH_FQDN+1]) {   
     WCHAR *pwszServerName = wszMachineName;      
  WCHAR *pwszTemp = pwszPath + 2;      
  WCHAR *end_addr = pwszServerName +MAX_COMPUTTERNAME_LENGTH_FQDN;

while((*pwszTemp!=L’\’)&&(*pwszTemp!=L’’)&&(pwszServerName            
  *pwszServerName++= *pwszTemp++;       
 /*… */   }

编辑:hfy


原文标题:嵌入式开发中的防御性C语言编程

文章出处:【微信号:gh_94c30763133f,微信公众号:STM32嵌入式开发】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
分享:

评论

相关推荐

好消息 飞凌嵌入式在电子发烧友企业号正式入驻啦

携手电子发烧友企业号Beta版上线,飞凌嵌入式在电子发烧友企业号正式入驻啦! 保定飞凌嵌入式技术有限....
的头像 电子发烧友网工程师 发表于 09-03 15:48 ? 154次 阅读
好消息 飞凌嵌入式在电子发烧友企业号正式入驻啦

STM32 单片机C语言课程3-C语言“函数”深入剖析

大家上午好!   今天为大家讲解C语言“函数”深入剖析,请持续关注,会持续进行更新! 前期回顾: ...
发表于 09-03 10:07 ? 101次 阅读
STM32 单片机C语言课程3-C语言“函数”深入剖析

变频器与逆变器的工作原理是什么

详解变频器、逆变器工作原理凡亿PCB  今天以下文章来源于嵌入式专栏 ,作者strongerHuang关注+星标公众号,不错过...
发表于 09-03 09:21 ? 0次 阅读
变频器与逆变器的工作原理是什么

嵌入式控制器CX5120-0125

本例程使用的是倍福嵌入式控制器CX5120-0125。变频器使用博能传动公司A1系列驱动器,支持EtherCAT通信。继续上一篇博文《...
发表于 09-03 08:58 ? 0次 阅读
嵌入式控制器CX5120-0125

步进电机的正反向旋转c语言编程

#include#include#define uchar unsigned char#define uint unsigned intuchar code CCW[8]={0x08,0x0c,0x04,0x06,0x02,0x03,...
发表于 09-03 06:05 ? 0次 阅读
步进电机的正反向旋转c语言编程

【含案例源码】IMX8基于FlexSPI、PCIe与FPGA的高速通信开发详解!

前 言本文主要介绍i.MX 8M Mini基于FlexSPI、PCIe与FPGA的高速通信案例。本文....
的头像 黄工 发表于 09-02 17:29 ? 34次 阅读
【含案例源码】IMX8基于FlexSPI、PCIe与FPGA的高速通信开发详解!

全志H5芯片香橙派zero plus开发板26pin的SPI功能测试

wiringOP 已适配 Orange Pi Zero Plus开发板,使用 wiringOP 可以测试 GPIO、I2C、UART 和 SPI 的功能。 ...
发表于 09-02 17:24 ? 0次 阅读
全志H5芯片香橙派zero plus开发板26pin的SPI功能测试

C语言代码中的extern

在你的C语言代码中,不知能否看到类似下面的代码: 这好像没有什么问题,你应该还会想:“嗯?是啊,我们....
的头像 STM32嵌入式开发 发表于 09-02 15:13 ? 76次 阅读
C语言代码中的extern

【stm32单片机】带定位系统的离心式微流控平台研究与设计

带定位系统的离心式微流控平台研究与设计 随着医疗水平和人民健康意识的提高,血液检测相关的医疗器械越来越受关注。目前国...
发表于 09-02 14:30 ? 0次 阅读
【stm32单片机】带定位系统的离心式微流控平台研究与设计

【原创推荐】什么是Map文件,它有什么用?

前面文章《不要再找啦,关于Cortex-Mx芯片的启动没有比这里更清楚啦》对STM32单片机的启动流程以及main函数的执行做了一个详...
发表于 09-02 14:20 ? 44次 阅读
【原创推荐】什么是Map文件,它有什么用?

嵌入式系统开发的思维和注重方法

开头的话 嵌入式开发是一个比较苦、容易背锅、可能仍然需要996而且拿钱较少,但也有些许乐趣的活,我一....
的头像 嵌入式ARM 发表于 09-02 11:10 ? 439次 阅读
嵌入式系统开发的思维和注重方法

电子发烧友企业号Beta版上线,入驻开启获客第一步

? ? NEWS 随着客户需求升级,电子产业供应链缺乏弹性、流量愈发昂贵、品类同质化等问题的凸显,对....
的头像 电子发烧友开放平台 发表于 09-02 11:01 ? 194次 阅读
电子发烧友企业号Beta版上线,入驻开启获客第一步

重磅发布 | iMX8MP 核心板,高性能、高集成,闪耀上市(文末有福利!)

飞凌i.MX8MP核心板处理器内部集成2.3TOPS算力(每秒兆级操作)的高性能NPU。 通过将高性....
的头像 栾新科 发表于 09-02 09:59 ? 269次 阅读
重磅发布 | iMX8MP 核心板,高性能、高集成,闪耀上市(文末有福利!)

c语言实现面向对象编程 精选资料分享

c语言的面向对象框架(以RT-Thread软件包rt-robot为例)概述??有一种说法是c语言是一门面向过程的语言,其实这种说法是比较...
发表于 09-02 07:46 ? 0次 阅读
c语言实现面向对象编程  精选资料分享

解决方案 | 基于全志T507核心板设计智能加油机应用

飞凌嵌入式FETT507-C核心板基于全志T507四核车规级处理器设计开发,可满足智能加油机的所有功....
的头像 栾新科 发表于 09-01 18:28 ? 19次 阅读
解决方案 | 基于全志T507核心板设计智能加油机应用

FCU1104双网数采网关在“碳中和”目标下的在线能耗监测方案

以智慧能源管理平台等辅助管理手段提高能源利用效率,实现节能减排,其中能耗在线监测平台无疑是投入少,性....
的头像 栾新科 发表于 09-01 18:28 ? 22次 阅读
FCU1104双网数采网关在“碳中和”目标下的在线能耗监测方案

全志T507操作小技巧连载2-T507以太网配置方法

本文硬件平台采用全志T507四核车规级处理器设计开发板,本文讲解T507开发板以太网配置方法。其它板....
的头像 栾新科 发表于 09-01 18:28 ? 15次 阅读
全志T507操作小技巧连载2-T507以太网配置方法

全志T507操作小技巧连载1-T507屏幕切换的两种方式

飞凌嵌入式FETT507-C核心板集成全志T507四核车规级处理器设计开发,Cortex-A53架构....
的头像 栾新科 发表于 09-01 18:27 ? 12次 阅读
全志T507操作小技巧连载1-T507屏幕切换的两种方式

全国产+5G+AI在智慧电力中的应用探索 Q&A问答

5G 改变社会,电力点亮未来。5G如何赋能智慧电网?应用场景有哪些? 保定飞凌嵌入式技术有限公司,....
的头像 栾新科 发表于 09-01 18:27 ? 21次 阅读
全国产+5G+AI在智慧电力中的应用探索 Q&A问答

干货讲解 | OKT507-C开发板如何在Android系统上进行OTA升级

OTA升级是Android系统所提供的标准软件升级方式。它功能十分强大,并且提供了完全升级(完整包)....
的头像 栾新科 发表于 09-01 18:27 ? 18次 阅读
干货讲解 | OKT507-C开发板如何在Android系统上进行OTA升级

网关方案应用 | 工业网关在空气环境监测系统解决方案

FCU1104工业网关与各类的传感器相连,对传感器的数据进行实时采集,通过LED屏幕将数据实时显示,....
的头像 栾新科 发表于 09-01 18:27 ? 22次 阅读
网关方案应用 | 工业网关在空气环境监测系统解决方案

FCU1104 专为物联网边缘计算网关而生

飞凌嵌入式最新产品FCU1104嵌入式控制单元正式发售!该平台采用了NXP超高效、高性能、低成本的i....
的头像 栾新科 发表于 09-01 18:27 ? 19次 阅读
FCU1104 专为物联网边缘计算网关而生

干货 | LS1028A-C如何输出PWM方波?

干货 | 飞凌OK1028A-C如何输出PWM方波? 最近,我收到了一个使用OK1028A-C输出....
的头像 栾新科 发表于 09-01 18:27 ? 16次 阅读
干货 | LS1028A-C如何输出PWM方波?

飞凌嵌入式iMX8MP系列OKMX8MPQ-C 软件手册

OKMX8MPQ-C开发板采用NXPi.MX8MPlus高性能处理器开发,内置NPU、ISP,AI计....
发表于 09-01 18:23 ? 10次 阅读
飞凌嵌入式iMX8MP系列OKMX8MPQ-C 软件手册

飞凌嵌入式iMX8MP系列OKMX8MPQ-C_硬件使用手册

i.MX8MPlus系列专注于机器学习和视觉、高级多媒体以及具有高可靠性的工业自动化。它旨在满足智慧....
发表于 09-01 18:23 ? 29次 阅读
飞凌嵌入式iMX8MP系列OKMX8MPQ-C_硬件使用手册

【原创推荐】MDK中Buil/ReBuild背后你不知道的故事

在程序开发过程中,大家都会去点击编译按钮,直接开始仿真调试,基本上不怎么关注编译和链接的过程,因为我们使用的工具一般都是...
发表于 09-01 16:31 ? 101次 阅读
【原创推荐】MDK中Buil/ReBuild背后你不知道的故事

Vector向量计算技术与SIMD技术的对比

关键词:RISC-V处理器 ,平头哥玄铁CPU,RISC-V指令集,IoT芯片,Vector,SIMD技术 什么是向量计算技术?什...
发表于 09-01 15:09 ? 101次 阅读
Vector向量计算技术与SIMD技术的对比

测评 | iMX8MM开发板,带你体验不同的影音体验

OKMX8MM-C是飞凌基于NXP公司i.MX8M Mini 四核64位处理器所设计的一款开发板,主....
的头像 栾新科 发表于 08-31 18:47 ? 40次 阅读
测评 | iMX8MM开发板,带你体验不同的影音体验

方案 | 基于全志T507核心板设计电子AI后视镜

电子AI后视镜终端产品可借助飞凌FETT507-C核心板实现,该核心板基于全志T507四核车规级处理....
的头像 栾新科 发表于 08-31 18:46 ? 26次 阅读
方案 | 基于全志T507核心板设计电子AI后视镜

基于FETMX8MP-C核心板的商用车智能驾驶终端

2019年3月,我国交通部发布了JT/T 1178.2,即《营运货车安全技术条例 第2部分:牵引车辆....
发表于 08-31 14:18 ? 172次 阅读
基于FETMX8MP-C核心板的商用车智能驾驶终端

C -与ORACLE直接连接代码

C -与ORACLE直接连接代码(肇庆理士电源技术有限)-C#-与ORACLE直接连接代码,有需要的....
发表于 08-31 11:18 ? 6次 阅读
C -与ORACLE直接连接代码

Git基础知识综述

Git基础知识综述
发表于 08-31 10:42 ? 14次 阅读
Git基础知识综述

Git常见的误区和命令行工具等综述

Git常见的误区和命令行工具等综述
发表于 08-31 09:51 ? 13次 阅读
Git常见的误区和命令行工具等综述

Mac苹果系统安装包DR4.5程序下载

Mac苹果系统安装包DR4.5程序下载
发表于 08-31 09:24 ? 19次 阅读
Mac苹果系统安装包DR4.5程序下载

DLMS协议蓝皮书英文版资源下载

DLMS协议蓝皮书英文版资源下载
发表于 08-30 14:29 ? 24次 阅读
DLMS协议蓝皮书英文版资源下载

C语言冒泡排序工程代码汇总

C语言冒泡排序工程代码汇总
发表于 08-30 11:06 ? 11次 阅读
C语言冒泡排序工程代码汇总

C语言文件读写工程源代码汇总下载

VB文件读写
发表于 08-30 10:42 ? 21次 阅读
C语言文件读写工程源代码汇总下载

21489图形化开发详解:Fireware的烧写与直通

本文介绍ADI SHARC DSP图形化开发,在一般我们都是使用vdsp++进行c语言开发的,但其实....
的头像 处理器世界 发表于 08-27 15:14 ? 1027次 阅读
21489图形化开发详解:Fireware的烧写与直通

嵌入式系统的内存指针操作

在嵌入式系统中,对内存地址的操作是一个重要的方面,从广义上讲,嵌入式系统的地址空间可以分成以下三种类....
的头像 电子发烧友网工程师 发表于 08-27 11:33 ? 1691次 阅读
嵌入式系统的内存指针操作

嵌入式系统编程的大小端和内存对齐问题

C语言是一种高级语言,在大多数情况下C语言的代码是和具体的处理器体系结构无关的。然而,在嵌入式系统的....
的头像 电子发烧友网工程师 发表于 08-27 10:54 ? 843次 阅读
嵌入式系统编程的大小端和内存对齐问题

大文件上传服务器、支持超大文件HTTP断点如何续传教程

最近由于笔者所在的研发集团产品需要,需要支持高性能的大文件http上传,并且要求支持http断点续传....
的头像 Android编程精选 发表于 08-26 15:36 ? 442次 阅读
大文件上传服务器、支持超大文件HTTP断点如何续传教程

手把手教你学51单片机-C语言版资源下载

手把手教你学51单片机-C语言版资源下载
发表于 08-26 14:51 ? 108次 阅读
手把手教你学51单片机-C语言版资源下载

嵌入式工控机和传统工控机的区别是什么

随着近些年来嵌入式工控机在行业当中的应用成熟起来,在一些行业或者是领域的当中已经取代一些传统的工控机....
发表于 08-26 14:36 ? 93次 阅读
嵌入式工控机和传统工控机的区别是什么

嵌入式Linux工程师的职业方向是什么

很多学习嵌入式的新人、工程师,在学习到半途中,总会感觉到迷茫,不知道自己从哪方面入手、进阶,也不知道....
的头像 硬件攻城狮 发表于 08-25 16:55 ? 229次 阅读
嵌入式Linux工程师的职业方向是什么

嵌入式UHF RAIN RFID模块ThingMagic M6e-Nano

ThingMagic Nano是Mercury系列嵌入式UHF RAIN RFID模块中最小的产品。....
发表于 08-25 15:23 ? 22次 阅读
嵌入式UHF RAIN RFID模块ThingMagic M6e-Nano

高性能多协议嵌入式RFID模块ThingMagic M6e

高性能多协议嵌入式RFID模块ThingMagic M6e
发表于 08-24 15:45 ? 37次 阅读
高性能多协议嵌入式RFID模块ThingMagic M6e

Microchip推出精确计时精度和稳定性新型SA65型芯片级原子钟

Microchip的SA65型芯片级原子钟是一款嵌入式计时解决方案,具有更好的环境适应性,与之前的S....
的头像 AMDRadeon显卡中国 发表于 08-24 09:46 ? 2243次 阅读
Microchip推出精确计时精度和稳定性新型SA65型芯片级原子钟

lex与yacc第二版电子版资源下载

lex与yacc第二版电子版资源下载
发表于 08-23 17:06 ? 137次 阅读
lex与yacc第二版电子版资源下载

鸟哥的Linux私房菜基础学习篇电子版下载

鸟哥的Linux私房菜基础学习篇电子版下载
发表于 08-23 16:14 ? 38次 阅读
鸟哥的Linux私房菜基础学习篇电子版下载

嵌入式和单片机究竟有什么区别

凡是从事信息技术相关工作的童鞋,一定都听说过嵌入式和单片机。 大家都知道,这两个名词,和硬件系统有着....
的头像 物联网标准化 发表于 08-23 15:26 ? 2746次 阅读
嵌入式和单片机究竟有什么区别

嵌入式工控机与普通工控机的区别,它有哪些优势

嵌入式工控机是一种加固的增强型工业计算机,它可以作为一个工业控制器在工业环境中可靠运行,嵌入式工控机....
发表于 08-23 13:54 ? 204次 阅读
嵌入式工控机与普通工控机的区别,它有哪些优势

C语言编程中如何求出二叉树后序遍历

题目 已知二叉树前序为 ABDFGCEH 后序序列为 BFDGACEH ,要求输出后序遍历为 FGD....
的头像 C语言编程基础 发表于 08-23 11:04 ? 977次 阅读
C语言编程中如何求出二叉树后序遍历

Keil C51 V9.00开发环境程序下载

Keil C51 V9.00开发环境程序下载
发表于 08-23 10:49 ? 26次 阅读
Keil C51 V9.00开发环境程序下载

嵌入式工控机在智慧停车场的应用

本期上海研强给大家分享的是嵌入式工控机在智慧停车场的应用,希望看完本篇文章您能对嵌入式工控机有一个全....
发表于 08-23 10:12 ? 44次 阅读
嵌入式工控机在智慧停车场的应用

嵌入式工控机在人工智能中的应用

  本期上海研强给大家分享的是嵌入式工控机在人工智能产业的应用,希望看完本篇文章您能对嵌入式工控机有....
发表于 08-23 10:09 ? 77次 阅读
嵌入式工控机在人工智能中的应用

贸泽开售适用于嵌入式本地语音助手应用的 NXP i.MX RT106S跨界处理器

 贸泽分销的NXP i.MX RT106S处理器是EdgeVerse?边缘计算平台中的一款产品。该处....
发表于 08-20 14:34 ? 745次 阅读
贸泽开售适用于嵌入式本地语音助手应用的 NXP i.MX RT106S跨界处理器

iMX8M Plus为边缘计算赋能-高性能的机器学习让边缘计算更给力

凭借可根据各类数据源(如摄像头输入)做出决策的边缘设备,用户能够将重要数据保存在本地网络中。这减少了....
的头像 栾新科 发表于 08-20 14:19 ? 124次 阅读
iMX8M Plus为边缘计算赋能-高性能的机器学习让边缘计算更给力

嵌入式移动存储解决方案新变化,512G成移动存储主流

近20年来,智能手机成为了对我们影响最大的电子产品。现在的手机承载了越来越多的功能,可以说,如今出门....
的头像 荷叶塘 发表于 08-19 01:13 ? 1806次 阅读
嵌入式移动存储解决方案新变化,512G成移动存储主流
一夜七次郎/61794视频在线播放/欧美成年性色生活片/第九色区a天堂