tag 标签: 嵌入式

相关帖子
相关博文
  • 热度 1
    2021-1-19 22:47
    214 次阅读|
    0 个评论
    原文: https://zhuanlan.zhihu.com/p/342410727 第一部分:基本概念 1.关键字static的作用 (1)在函数体内:一个被声明为静态的变量,在这一函数被调用过程中,维持其值不变。(该变量值初始化一次) (2)在模块内,函数体外:一个被声明为静态的变量,可以被模块内所用函数访问,但不能被模块外其他函数访问。 (3)在模块内,一个被声明为静态的函数,该函数只能被这一模块内其他函数调用,其他模块无法调用。 2.引用与指针的区别: (1)引用必须初始化,指针不用 (2)引用初始化后不能修改,指针可以改变所指对象 (3)不存在指向空的引用,指针存在空值 指针通过某个指针变量指向一个对象后,对它所指向的变量间接操作。 引用本身就是目标变量的别名,对引用的操作就是对目标变量的操作。 关-注-公-众-号:嵌入式基地 回-复:【面试】 获-取-面-试-资-料 3..h头文件中的#ifndef/#define/#endif作用: 防止头文件被重复引用 4.#include 与#include “”区别: 是从系统指定的路径下寻找;””是先从当前路径下寻找 5.描述实时系统的基本特性: 在特定时间内完成特定的任务,实时性与可靠性。 6.全局变量与局部变量是否存在区别? 全局变量存在静态数据区,局部变量存在栈中 7.堆栈溢出一般是由于什么原因? (1)没有回收垃圾资源 (2)层次太深的递归调用 8.冒泡排序算法的时间复杂度 O(n^2) 9.什么函数不能声明为虚函数? 构造函数 10.队列与栈的区别: 队列:先进先出;栈:先进后出 11.不能做switch()的参数类型 实型 12.局部变量是否能和全局变量重名? 可以。局部变量会屏蔽全局变量。若要使用全局变量,使用::。 在函数内引用该重名变量时,会使用同名的局部变量,而不会使用全局变量(就近原则)。 对一些编译器而言,同一函数内可以定义多个同名的局部变量,例如:在两个循环体内都定义一个同名的局部变量,而那个局部变量的作用域就在该循环内。 13.如果引用一个已经定义过的全局变量? 可以包含其头文件,也可使用关键字extern。 引用头文件:通过引用头文件的方式来引用某个头文件中声明的变量,假如将该变量写错了,在编译阶段会报错。 Extern:通过extern的方式引用,若将变量写错,编译阶段编译器不会报错,在链接阶段会进行报错提示。 14.全局变量能不能定义在可被多个.c文件包含的头文件中? 可以。在不同的C文件中以static的形式来声明同名全局变量。 可以在不同的C文件中声明同名的全局变量,前提是只能在一个C文件中对变量赋初值,此时链接不会报错。 15.for(;1;)有什么问题?什么意思? 与while(1)相同,无限循环 16.do…while()与while…do有什么区别? 前者循环一遍后再判断;后者先判断后循环 17.static全局变量、局部变量、函数与普通全局变量、局部变量、函数有什么区别? (1)static全局变量与非static全局变量区别: 存储方式上相同,都是静态存储。 作用域:非static全局变量的作用域在各个文件中都是有效的;static的全局变量作用域只限于当前源文件中,只初始化一次。 (2)static函数与普通函数作用域不同。Static函数只能在当前源文件中使用,而非Static函数可以在其他源文件中使用。 (3)static局部变量只初始化一次,下次调用使用上次的数值。 18.程序的内存分配 C/C++编译的程序占用的内存分为以下几部分。 (1) 栈区,编译器自动分配释放,存放函数的参数值,局部变量的值等。操作方式类似于数据结构中的栈。 (2) 堆区,由程序员分配释放。若程序员没有进行资源回收,程序结束时,可能会由OS回收。与数据结构中的堆是两回事。 (3) 全局区(静态区),全局变量与静态变量是存储在一起的。初始化的全局变量与初始化的静态变量在一块区域,未初始化的全局变量与未初始化的静态变量存储在一起。程序结束后由OS释放 (4) 常量区,存储常量,字符串。程序结束后由OS回收。 (5) 程序代码区,存放函数体的二进制代码。 示例: int a = 0; //全局初始化区域 char *p1; //全局未初始化区域 int main(int argc, char const *argv = “ssssss”; Char *s2 = “bbbbbb”; aaaaaa是在运行时赋值的,bbbbbb是在编译时确定的。 但在以后的存取中,栈上的数组比指针指向的字符串(堆)块。 void main() { char a = 1; char c ; a = p ; return; } 对应的汇编代码 10:a=c ; 004010678A4DF1movcl,byteptr 0040106A884DFCmovbyteptr ,cl 11:a=p ; 0040106D8B55ECmovedx,dwordptr 004010708A4201moval,byteptr 004010738845FCmovbyteptr ,al 第一种:在读取时,直接将字符串中的元素读到寄存器c1中 第二种:先将指针读取到edx中,再根据edx读取字符。 20.什么是预编译,什么时候需要预编译? 预编译又称为预处理,是做代码文本的替换工作,处理#开头的指令,比如拷贝#include包含的头文件代码;#define宏定义的替换。在程序开始编译之前进行。 C语言编译系统在对程序编译之前,先进行预处理。预处理主要提供以下功能: (1)宏定义(2)头文件包含(3)条件编译 21.关键字const含义 const 只读 应用: const int a; //常整型数 int const a; //常整型数 const int *a; //a是一个指向常整型数的指针(指针可以修改,整型数不可修改) int * const a; //a是一个指向整型数的常指针(指针不可以修改,整型数可以修改) const int * const a; //a是一个指向常整形数的常指针(都不可修改) 使用const关键字的理由: (1) 为读代码的人提供非常有用的信息,实际上应用一个参数为常量是为了告诉用户这个参数的应用目的。 (2) 通过给优化器一些附加信息,使用关键字const也许能够产生更紧凑的代码 (3) 合理使用const可以使编译器很自然的保护那些不希望被修改的参数,防止其被无意的代码修改。 22.关键字volatile含义?应用例子: 含义: 一个被定义为volatile的变量是说这个变量可能会被意想不到的改变,这样编译器就不会去假设这个变量的值了。准确的说,优化器在用到这个变量时,必须每次都小心点重新读取这个变量的值,而不是直接使用寄存器中的备份值。 应用: (1)并行设备的硬件寄存器 (2)一个中断服务子程序中会访问到的非自动变量。 (3)多线程应用中被几个任务共享的变量 其他问题: 1. 一个参数既可以是const还可以是volatile吗?为什么? 2. 一个指针可以是volatile吗 3. 下面函数有什么错误 Int square(volatile int *ptr) { Return *ptr * *ptr; } (1) 可以,一个例子为只读的状态寄存器。它是volatile是应为他可能被意想不到的改变。它是const是应为程序不因该去修改它。 (2) 是的,虽然不常见。一个例子为中断服务子程序修改一个指向一个buffer的指针时。 (3) 这段代码的目的是为了返回指针*ptr的平方,但是由于*ptr是一个指向volatile类型的参数,因此编译器将产生类似于下面的代码: int square(volatile int *ptr) { int a, b; A = *ptr; B = *ptr; Return a * b; } 由于*ptr的值可能被意想不到的改变,因此,a与b的值可能不同,结果这段代码返回的结果与预期可能并不相同。 正确代码: int square(volatile int *ptr) { int a; A = *ptr; Return a * a; } 23.三种基本数据模型 按照数据结构类型的不同,将该数据模型划分为层次模型、网状模型、关系模型 24.结构体与联合体有什么区别 共用体,允许在相同的内存地址存储不同的数据类型;可以定义一个带有多成员的共用体,但是任何时候只能有一个成员带有值。共用体提供了一种使用相同内存地址的方式 共用体,占用的内存应该足够存储共用体中最大的成员。 结构体,占用内存是内部所有变量所占空间之和。结构体,每个成员变量都有自己的内存地址。 25.#define与const区别: 1.const有数据类型,宏定义没有数据类型;编译器可以对前者进行安全检查,对于后者不能进行安全检查,只能进行字符替换。 2.有些调试工具可以对const进行调试,而宏定义无法调试。 3.const定义的常量有作用域,而#define不重视作用域,默认定义处到文件结尾。 26.数组与指针区别: 数组要么在静态数据区被创建,要么在栈上被创建。 指针可以随时指向任意类型的内存块。 (1)修改内容上的差别: char a = ‘x’; Char *p = “world”;//p指向的是常量字符串 P = ‘x’;//编译器无法发现该错误,运行时会报错 (2)使用sizeof()运算符计算容量: 数组可以使用sizeof计算出容量,而sizeof(p)计算得到的是一个指针变量的字节数,一般为4个字节,而不是p所指向的内存容量。 注意:当数组作为函数形参进行传递时,该数组自动退化为同类型指针: void TestBufferSize1(char a ) { printf("buffer size = %d \r\n", sizeof(a)); } int main(){ char b = "12345"; printf("b size = %d \r\n", sizeof(b)); TestBufferSize1(b); TestBufferSize2(b); system("pause"); } 27.分别写出bool、int、float、指针类型的变量a与零比较的语句: (1)bool: If(!a) or if(a) (2)int If(a == 0) (4)float: Const EXPRESSION EXP = 0.000001 If(a -EXP) (5)指针: If(a != NULL) or if(a == NULL) 28.如何判断一段程序是由c编译还是由c++编译程序编译的? #ifdef __cplusplus cout << "c++"; #else printf("c"); #endif 29.讨论含参数的宏与函数优缺点: 带参宏 函数 处理时间 编译时 程序运行时 参数类型 没有参数类型问题 定义实参,形参类型 处理过程 不分配内存 分配内存 程序长度 变长 不变 运行速度 不占用运行时间 调用和返回占用运行时间 30.使用两个栈来实现一个队列的功能 设两个栈A,B,并将其初始化为空 入队: 将新元素push入栈A; 出队: (1) 判断栈B是否为空 (2) 若不为空,则将栈A中的所有元素依次pop出,并push到栈B (3) 将栈B的栈顶元素pop出 这样的实现,入队与出队的平摊复杂度都为O(1) 31.位操作 给定一个整型变量a,写两段代码,第一个设置a的bit 3,第二个清除a的bit 3。在以上操作中,保持其它位不变。 (1) 通过宏定义,以及bit masks操作。这种方法可移植性高 #define BIT3 (0x01 << 3) static int a; void SetBit3(void) { a |= BIT3; } void ClearBit3(void) { a &= ~BIT3; } (2) 使用bit fields。Bit fields是被扔到C语言死角的方式。这种方法保证了你的代码在不同编译器之间是不可移植的,同时也保证代码是不可重用的。 32.访问固定的内存位置 嵌入式编程中,经常会去访问某个特定内存位置的数据。在某个工程中,需要设置一个绝对地址为0x56a3的整型变量的值为0x3344。编译器是一个纯粹的ANSI编译器。 (1) 方法一: int *ptr = NULL; ptr = (int *)0x56a3; *ptr = 0x3344; (2) 方法二: *(int * const)(0x56a3) = 0x3344; 推荐使用第一种。 33.中断 中断是嵌入式系统中重要的组成部分,这导致了很多编译开发商提供了一种扩展—让标准C支持中断。 具体代表的事实是,产生了一个新的关键字__interrupt。 下面这段代码使用了__interrupt关键字去定义了一个中断服务子程序(ISR),请评价这段代码。 __interrupt double compute_area(double radius) { double area = PI * radius * radius; printf("\nArea = %f", area); return area; } (1) ISR不能返回一个值 (2) ISR不能传递参数 (3) 在许多编译器中,浮点数一般是不可重入的。并且,ISR应该是短而有效的,在ISR中做浮点数运算是不明智的。 (4) Printf()经常有重入与性能上的问题 34.typedef Typedef 在C语言中频繁用以声明一个已经存在的数据类型的同义字。也可以用预处理器做类似的事情。 例: #define dPS struct s * Typedef struct s *tPS; 以上两种情况都是要定义dPS和tPS作为一个指向结构s的指针。哪种方法更好? 答:typedef更好,原因请看下面示例。 dPS s1,s2; tPS s3,s4; 第一个展开为struct s *s1,s2;此时,s1指向的是结构的指针,而s2是一个实际的结构。 35.写一个“标准”的宏 (1)交换两个参数的宏定义 #define SWAP(a, b)\ (a) = (a) + (b);\ (b) = (a) - (b);\ (a) = (a) - (b);\ (2)输入两个参数,输出较小的参数 #define MIN(a, b) (((a) < (b)) ? (a) : (b)) (3)1年中有多少秒?(忽略闰年) #define SECONDS_OF_YEAR (60 * 60 * 24 * 365)UL (4)已知一个数组table,使用宏定义求出数组元素的个数 #define TABLE_SIZE (sizeof(table) / siezof(table ))
  • 热度 3
    2020-12-26 14:07
    466 次阅读|
    0 个评论
    关键词:Modbus FreeModbus STM32F103C8T6 CubeMX 移植 摘要:STM32F103、FreeModbus从站设计(5)-如何将FreeModbus代码加入keil。详细阐述如何获取freemodbus代码,代码的大体结构,如何将freemodbus加入keil工程。讲解了注意事项,全实战演示,实际可用。 1.前提 (1)管脚配置 图1 (2)外设资源 图2 2.FreeModbus协议代码添加 (1)获取代码 最新的FreeModbus协议代码可以在其官网下载,孔丙火(微信公众号:孔丙火)提醒,是下载免费的那个版本,仅支持从站,支持主站的版本是收费的。 图3 (2)添加代码到工程 Freemodbus的代码中需要复制的是modbus和demo两个文件夹,把modbus文件夹整个拷贝到工程目录中,把demo-bare中的port文件夹拷贝到工程目录中,把demo-bare中的demo.c拷贝到工程目录的Src文件夹中,孔丙火(微信公众号:孔丙火)把它改名为:modbus_app.c,如图4。 图4 在keil工程中新建一个Group,命名为:modbus,把modbus文件夹中所有文件添加到其中,然后新建一个名为prot的Group,把port文件夹中所有文件添加到其中,把modbus_app.c添加到名为Application/User的已有Group中,如图5。 图5 (3)头文件包含路径修改 在工程的魔术棒选项中,把添加到工程中的所有子文件夹添加到包含路径中,如图6所示。 (4)编译 把modbus_app.c中的main函数注掉,因为一个工程中只能有一个main函数,然后编译,没有错误,有4个warning,这个在后续的代码修改后,会消除。 图6 单片机、ARM、现场总线、PLC、嵌入式软硬件的设计经验分享,秉承“点点滴滴皆智慧”的理念,以实际项目为单元阐述知识点,一起分享,共同交流。 文章在微信公众号(孔丙火)同步推出,欢迎欣赏更多精彩文章。
  • 热度 2
    2020-12-8 16:19
    540 次阅读|
    0 个评论
    关键词:Modbus FreeModbus STM32F103C8T6 CubeMX 1.串口参数设置 我们选择UART2来做RS485接口,UART1作为备用,用来做调试中的串口打印用。串口的参数配置比较简单,不再赘述。注意要启用串口中断,FreeModbus采用中断的方式接受和发送串口数据。 2.定时器参数设置 采用TIM2来作为FreeModbus的定时器,孔丙火(微信公众号:孔丙火)这里主要实现工业控制中常用的Modbus-RTU功能,RTU协议中是靠时间间隔来判断一个数据帧是否结束的,所以需要用到定时器。 先上一张时钟配置图,如图1. 图1 晶振是12M的,APB1和APB2的定时器频率都是72M。 图2 图2是TIM2的参数配置界面,时钟分频是3599+1=3600,即:72÷3600=0.02MHz,一个时钟周期为:1÷0.02M=50us,之所以这样设置,是基于Freemodbus协议的需要。熟悉Freemodbus协议的朋友是知道的,在通信速率≥19200pbs时,帧间隔识别时间为固定的35×50us=1750us,在通信速率<19200pbs时,按照实际的11个bit时间计算。孔丙火(微信公众号:孔丙火)在这里暂且把Counter Period设为35,其实在程序代码中是根据实际通信速率来赋值的,这个在后面的文章中会详细介绍。这个地方也是本系列文章与网上大多数文章的不同支出,其他文章多数把这个参数设为固定值,每次更改通信速率都要手动改这个参数,孔丙火(微信公众号:孔丙火)感觉不是很方便。 3.中断说明 图3 如图3所示,中断部分的配置至少要使能TIM2和USART2的中断。在程序中,实际用到的是TIM2的定时溢出中断,UART2的接收完成中断和发送非空中断。 把这些设置完后,就可以去生成代码了,这一步比较简单,不再赘述,不太清楚的朋友,也可以参考孔丙火(微信公众号:孔丙火)之前的文章。下一节开始详细介绍代码的编写。 单片机、 ARM 、现场总线、 PLC 、嵌入式软硬件的设计经验分享,秉承 “ 点点滴滴皆智慧 ” 的理念,一起分享,共同交流。
  • 热度 9
    2020-9-2 14:40
    1736 次阅读|
    4 个评论
    多功能按键嵌入式程序设计
    1. 按键算法简介 这是一种多功能按键的嵌入式程序设计算法,它支持按键检测规则可配、多种按键事件和最大 32 数量的按键检测,该算法首先是通过读取芯片管脚 IO 电平的变化,再经过滤波和自定义规则算法输出按键事件,最终达到用户所需要功能的目的。如在单一按键中,可以有单击、双击、三击、短按、长按和超长按等事件,不同的事件可以自定义不同的功能。用户通过简单的初始化 GPIO 再加上按键检测算法,就容易实现按键多功能。它的应用场合,如 TWS 耳机、助听器、电子手表、单按键智能插座和智能灯控面板等。 1.1. 按键规则设计 按键检测规则如下: 名称 英文 范围 ( ms ) 设置值 长按 Long p ress 0 -12000 1 500 超长按 Long Long p ress 0 -12000 4 000 超超长按 Long Long Long p ress 0 -12000 8 000 双击 D ouble Press 0-1000 6 00 三击 Triple P ress 0-1000 800 重复 时间间隔 repeat rate 0-1000 4 00 滤波次数 Number Of F ilter 0 -255 2 检测周期 C hecks Cycle 0 -255 2 0 按键执行 Key A ctive L OW: 低电平有效,需要配置成上拉 H IGHT: 高电平有效,需要配置成下拉 L OW 低电平有效 1.2. 按键事件类型 按键事件类型如下: 名称 英文 备注 单击 KEY _TYPE_SINGLE 双击 KEY _TYPE_DOUBLE 三击 KEY _TYPE_TRIPLE 短按 KEY _TYPE_LONG 短按 _ 释放 KEY _TYPE_LONG 长按 KEY _TYPE_LONG 长按 _ 释放 KEY _TYPE_LONG _ RELEASE 超长按 KEY _TYPE_VLONG 超长按 _ 释放 KEY _TYPE_VLONG _ RELEASE 超超长按 KEY _TYPE_VVLONG 超超长按 _ 释放 KEY _TYPE_VVLONG _ RELEASE 2. 程序展示 按键检测首先要对按键进行编号,按键序号码:第一个按键为 KEY1 ,第二个按键为 KEY2 ,第三个按键为 KEY3 ,若需要有更多按键可以往上加 KEY4 、 KEY5...KEYn , n<=31 。按键序号在按键输入和输出事件启到指定按键。 在程序设计中做一个枚举结构如下: enum { KEY1=0, KEY2, KEY3 }; 2.1. 按键检测初始化 初始化需要预先初始化 mark ,告诉算法需要检测按键的序号,检测规则需改变, 可以使用规则参数配置的结构体赋值,调用 void Button_SetKeyConfig(BUT_cfg_t KeyConfig) 函数,将参数传递进去。如果按照默认参数,就不需要重新初始化。 2.2. 按键 GPIO 高低电平采样 tKey_code 有 0-31(bit) ,其中 KEY1 为第 0bit ,它的值是 BUTTON1_DIO 管脚高低电平的值, 0 为低电平, 1 为高电平。所以表达式为 tKey |= 管脚电平状态? (1UL<
  • 热度 1
    2020-1-10 16:46
    794 次阅读|
    0 个评论
    【兆易创新RISC-V开发板评测】初评之STM32F103VBT6、GD32VF103VBT6特性比较
    笔者申请这款开发板的本意就是想对比常用的 STM32 家族芯片与 RISC-V 内核芯片在使用上的相同与不同之处,深入了解全球第一款 RISC-V 内核 32 位通用 MCU 本身的特性性能以及编程体验,以便在以后的项目中在微控制器的选择上做出权衡。因此,在拿到开发板后,有必要写一篇 STM32 系芯片与 GD 系芯片特性参数对比报告,扩大今后 MCU 的选择范围。兆易创新以 VF103 来命名第一款 RISC-V 内核的微处理器必然是对标 STM 公司 F103 系列微处理器,为了公平起见,本片测评以 STM 公司的 STM32F103VBT6 芯片和兆易创新的 GD32VF103VBT6 芯片从内核、容量、时钟、电源要求、管脚兼容性、主要外设几个方面做一个简单对比。 1. 内核 STM32F103 系列采用 ARM 公司 Cortex-M3 内核,核心频率最大 72MHz ,在零等待状态访问快闪存储器时计算性能可达 1.25DMIPS/MHz ,具有单周期乘法器和硬件除法器。 GD32VF103 系列采用芯来科技 Bumblebee 内核,核心频率最大 108MHz ,在零等待状态访问快闪存储器时计算性能可达 153DMIPS ,具有单周期乘法器和硬件除法器。 2. 容量对比 STM32F103 系列提供片上 16~1024KBytes FLASH 存储器, 6~96KBytes 静态 RAM 存储器, STM32F103VBT6 本身提供 128KBytes FLASH 和 20KBytes SRAM 。 GD32VF103 系列提供片上 16~128KBytes FLASH 存储器, 6~32KBytes 静态 RAM 存储器, GD32VF103VBT6 本身提供 128KBytes FLASH 和 32KBytes SRAM 。 3. 时钟对比 STM32F103VBT6 支持外部输入 4~16MHz 时钟信号,拥有 8MHz 和 40KHz 出厂校验的内部 RC 时钟。 GD32VF103VBT6 支持外部输入 3~25MHz 时钟信号,同样拥有 8MHz 和 40KHz 出厂校验的内部 RC 时钟。图 1 和图 2 分别为 STM32F103VBT6 和 GD32VF103VBT6 外设时钟树。 图 1 STM32F103VBT6 时钟树 图 2 GD32VF103VBT6 时钟树 4. 供电和功耗模式对比 STM32F103 供电范围支持 2.0~3.6V 电源供电,有单独供电引脚为 RTC 和备份寄存器供电,支持睡眠、停止和待机模式。 GD32VF103VBT6 供电范围支持 2.6~3.6V 电源供电,同样有单独供电引脚为 RTC 和备份寄存器供电,支持睡眠、深度睡眠和待机模式。图 3 和图 4 分别为 STM32F103VBT6 和 GD32VF103VBT6 电源域。 图 3 STM32F103VBT6 电源域 图 4 GD32VF103VBT6 电源域 5. 管脚兼容性 STM32F103VBT6 和 GD32VF103VBT6 脚位完全兼容,可以相互替换,图 5 和图 6 分别为 STM32F103VBT6 和 GD32VF103VBT6 脚位图。 图 5 STM32F103VBT6 脚位图 图 6 GD32VF103VBT6 脚位图 6. 主要外设对比 图 7 和图 8 为 STM32F103VBT6 和 GD32VF103VBT6 外设概览。 图 7 STM32F103VBT6 外设概览 图 8 GD32VF103VBT6 外设概览 6.1UART/USART STM32F103VBT6 拥有 3 个 USART ,其中 USART0 最高通信速率可达 4.5Mbit/s , USART1 、 USART2 最高可达 2.25Mbit/s 。 GD32VF103VBT6 拥有 5 个 U(S)ART ,其中 USART0 最高通信速率可达 6.75Mbit/s 。 6.2 定时器 STM32F103VBT6 拥有 1 个具有互补通道输出的 16 位高级定时器, 3 个 16 位通用定时器, 1 个 12 位向下计数独立看门狗, 1 个 7 位向下计数窗口看门狗和 1 个 24 位向下计数系统滴答定时器。 GD32VF103VBT6 拥有 1 个具有互补通道输出的 16 位高级定时器, 4 个 16 位通用定时器, 2 个 16 位基本定时器, 1 个 12 位向下计数独立看门狗, 1 个 7 位向下计数窗口看门狗和 1 个 64 位向上计数系统滴答定时器。 6.3SPI STM32F103VBT6 拥有 2 个 SPI ,可工作于主 / 从模式、全双工 / 半双工模式,最高通信速率可达 18Mbit/s 。 GD32VF103VBT6 拥有 3 个 SPI ,可工作于主 / 从模式、全双工 / 半双工模式,最高通信速率可达 27Mbit/s 。 6.4IIC STM32F103VBT6 拥有 2 个 IIC ,可工作于多主机模式和从机模式,传输支持标准和快速模式。 GD32VF103VBT6 同样拥有 2 个 IIC ,可工作于主机模式和从机模式,传输支持标准和快速模式。 6.5ADC STM32F103VBT6 拥有 2 个 12 位 ADC ,每个 ADC 共享 16 个外部输入通道,可工作于单次模式和扫描模式,支持外部触发采集。采集范围 2.4~3.6V ,最大采样速率 1MHz 。 GD32VF103VBT6 拥有 2 个 12 位 ADC ,每个 ADC 共享 16 个外部输入通道,可工作于单次模式和扫描模式,支持外部触发采集。采集范围 2.6~3.6V ,最大采样速率 1MHz ,可配置为 12 位、 10 位、 8 位或 6 位采样精度。 6.6USB STM32F103VBT6 拥有 1 个全速 12Mbit/s USB2.0 Host/Device/OTG 设备, D+ 引脚需经 1.5K Ω电阻上拉到 3.0~3.6V 电平。 GD32VF103VBT6 拥有一个全速 12Mbit/s USB2.0 Host/Device/OTG 设备, D+ 引脚上拉电阻已经集成在内部全速 PHY 内部。 6.7CAN STM32F103VBT6 拥有 1 个 CAN 总线接口,而 GD32VF103VBT6 拥有 2 个 CAN 总线接口。 6.8 其它 GD32VF103VBT6 拥有 2 个 12 位独立 DAC ,并可配置为 8 位或 12 位模式;拥有 16 位数据宽度的外部内存控制器,支持 SRAM , PSRAM , ROM 和 NOR-Flash 以及 6800 、 8080LCD 接口。 7. 总结 整体来说, GD32VF103 相对于同一梯队的 STM32 产品来说,不仅核心频率更高,而且外设也更丰富,配置也更灵活,毕竟是新时代的新生儿。通过以上比较,可以看出兆易创新在全球第一款基于 RISC-V 内核 32 位通用 MCU 身上下的功夫以及替代 ARM 的决心,作为国人,也应当支持。这一篇评测主要是对两种不同内核的 MCU 产品有一个初步比较认识,下一篇评测则专注两种芯片具体功耗和性能比较。
相关资源
广告