你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

查看: 2788|回复: 8

ARM®mbed OS入门开发 mbed 程序的语言基础 转

[复制链接]

61

主题

1071

回帖

17

蝴蝶豆

论坛元老

最后登录
2020-12-9
发表于 2016-10-23 21:48:34 | 显示全部楼层 |阅读模式
本帖最后由 anywill 于 2016-10-23 21:53 编辑

mbed 程序的语言基础
mBed程序采用C++进行编写,并在此基础上添加了一些自定义的函数和常量,所以我们在这有必要简单地了解一下相应的语言基础。

常量
常量是在程序运算过程中不变的量,常量在程序中经常直接出现,如数字1768;字符‘m’;字符串“mbed”等,
此时只要求它们符合相应类型数据的表示方法。相应于各种数据类型,有整型常量浮点型常量、字符型常量及字符串常量
有时为了代码编写的方便,我们会用一个标识符来代表一个常量,通过宏定义预处理指令来实现,这就是常量定义,
格式如下:
#define 标识符常量 由用户命名的标识符是符号常量名。
作为符号常量名,一般大写,一旦定义,在程序中凡是出现常量的地方均可用符号常量名来代替,
对使用了符号常量的程序在编译前会以实际常量替代符号常量。mbed中定义的常量举例如下:
#define DEVICE_ANALOGIN         1 //是否支持ADC采集
#define DEVICE_ANALOGOUT        1 //是否支持DAC输出
   变量及其数据类型
只要没有超过内存限制,mBed可以按照C++语法自由定义变量,但变量的数据类型必须是以下类型之一:
bool布尔类型,只有true和false两个值,分别代表数值1和0,占用1个字节。
char字符类型,用来表示一个字符但存储为字符的ASCII值,数值范围是-128到127,占用1个字节。
byte字节类型,数值范围是0到255,占用1个字节。
short短整型,数值范围是-32768到32767,占用2个字节。
unsigned short无符号短整型,数值范围是0到65535,占用2个字节。
int整型,数值范围是-2^31到2^31-1,占用4个字节。
unsigned int无符号短整型,数值范围是0到2^32-1,占用4个字节。
long长整型,数值范围是–2^63到2^63-1,占用8个字节。
unsigned long无符号长整型,数值范围是0到2^63,占用8个字节。
float浮点型,用来表示小数,占用4个字节。
double高精度浮点型,用来表示小数,占用8个字节。
Array数组类型,如下面的定义:
int light[6] = {0, 20, 50, 75, 100,150};
    枚举
在实际问题中,有些变量的取值被限定在一个有限的范围内。
例如,LPC1768的UART只能是UART0、UART1、UART2、UART3,I2C只能是I2C0、I2C1、I2C2等等。
如果把这些量说明为整型,字符型或其它类型显然是不妥当的。
为此,C/C++语言还提供了一种称为“枚举”的类型。
在“枚举”类型的定义中列举出所有可能的取值,被说明为该“枚举”类型的变量取值不能超过定义的范围。
定义一个变量是枚举类型,可以先定义一个枚举类型名,
然后再说明这个变量是该枚举类型,也可以直接定义枚举类型变量,mBed中一般采用的是后者,
如下面的例子:
typedefenum {
    SPI_0 = (int)LPC_SSP0_BASE,
    SPI_1 = (int)LPC_SSP1_BASE
} SPIName;
typedefenum {
    I2C_0 = (int)LPC_I2C0_BASE,
    I2C_1 = (int)LPC_I2C1_BASE,
    I2C_2 = (int)LPC_I2C2_BASE
} I2CName;
对于枚举类型的使用,我们需要理解以下几点:
l  枚举元素不是变量,而是常数,因此枚举元素又称为枚举常量,因为是常量,所以不能对枚举元素进行赋值。  
l  枚举元素作为常量,它们是有值的,C/C++ 语言在编译时按定义的顺序使它们的值为 0,1,2,…;
如果在定义枚举类型时指定元素的值,也可以改变枚举元素的值,
如下面的定义,它就是从1开始的,需要注意的是,枚举元素的值是可以相同的。
typedefenum {
    PWM_1 = 1,
    PWM_2,
    PWM_3,
    PWM_4,
    PWM_5,
    PWM_6
} PWMName;
typedefenum {
    // LPC Pin Names
    P0_0 = LPC_GPIO0_BASE,
          P0_1, P0_2,
    // mbed DIP Pin Names
    p5 = P0_9,
    p6 = P0_8,
    p7 = P0_7,
    p8 = P0_6,
    p9 = P0_0,
    p10 = P0_1,
    p11 = P0_18,
    p12 = P0_17,
   …
    // Not connected
    NC = (int)0xFFFFFFFF
} PinName;
l  枚举值可以用来作判断。枚举值的比较规则是:按其在说明时的顺序号比较,如,PWM5>PWM3。
l  一个整数不能直接赋给一个枚举变量,必须强制进行类型转换才能赋值。
例如:  pwm=(enum PWMName)2;这个赋值的意思是,将顺序号为2 的枚举元素赋给 pwm,相当于pwm =PWM_2
在mBed代码中,有大量的枚举类型,而且和常量定义结合紧密,如下面的代码,后面的常量值都是枚举元素:
// Default peripherals
#define MBED_SPI0         p5, p6, p7, p8
#define MBED_SPI1         p11, p12, p13, p14
#define MBED_UART0        p9, p10
#define MBED_UART1        p13, p14
#define MBED_UART2        p28, p27
#define MBED_UARTUSB      USBTX, USBRX

   运算符
         mBed使用C/C++的运算符,包括数学运算法、逻辑运算符和二进制运算符三部分内容。
         数学运算符:支持加(+),减(-),乘(*),除(/),求余(%)五种基本运算,需要注意的是,参与运算的数据类型的不同会导致结果的不同,如都是整型的情况下10/3=3,而有浮点型参与的情况下10/3.0=3.3,也就是说运算结果的数据类型和参与运算的数据类型相关,同时还要考虑运算结果的溢出情况,如下面的代码,理想结果是1000,实际结果却是232,就是1000溢出后的结果:
byte i=10;
    i=i*100;
         逻辑运算符:支持非(!),与(&&),或(||)三种逻辑运算符。
二进制运算符:支持按位非(!),支持按位与(&),支持按位或(|),支持按位异或(^),左移(>>),右移(<<)6中二进制运算符。
    控制结构
mBed使用C/C++的控制结构即以下四种类型:
if…else条件判断结构,下面的代码只有val=1的时候才把led管脚置高:
if (val == 1) {
    led=1;
}
Else{
    led =0;
}
for: 循环结构,下面的代码会把管脚置高10次:
for (int i = 0; i < 10; i++) {
led=1;
wait(1);
}
switch case分支结构,下面的代码会根据val的值把不同的管脚置高:
switch (val) {
case 1:
led1=1;
break;
case 2:
led2=1;
break;
default:
}
while/do while循环结构,下面的代码会把管脚置高512次,while/do while的区别是while里面的循环体有机会一次都不执行,而do while循环体至少执行1次:
int val = 0;
while (sensorValue < 512) {
led1=1;
wait(1);
val++;
}
do {
led1=1;
wait(1);
val++;
} while (val < 512);
在循环结构中我们需要合理利用break和continue关键词,前面表示直接跳出循环而continue表示跳过本次循环,如下面的代码,当x值不在140到200之间时,程序将跳过后续的led1=1;wait(1);然后开始下一轮循环:但如果采用break,程序将直接跳出for循环,执行代码led1=1。
for (light = 0; light < 255; light++)
{
if ((x > 140) && (x < 200))
continue;
led1=1;
wait(1);
}
led2=1;
  时间等待函数
         考虑到所有的应用都会用到时间等待函数,如前面例子中的wait,所以我们也把时间等待函数放在程序设计基础中介绍,mBed一共提供了三个时间等待函数,其具体实现如下:
void wait(float s) {
    wait_us(s * 1000000.0f);
}
void wait_ms(int ms) {
    wait_us(ms * 1000);
}
void wait_us(int us) {
    uint32_t start = us_ticker_read();
    while ((us_ticker_read() - start) < (uint32_t)us);
}
      从中可以看出,这三个函数的本质都是wait_us,需要注意的是,wait函数输入的是浮点类型,单位是秒,wait_ms和wait_us输入的都是整形,单位分别是毫秒和微妙,而这里用到的us_ticker_read()也是一个很常用的时间函数,表示系统reset后已经运行了多长时间了。
现在我们可以综合利用上面的一些函数完成新的HelloWorld程序了,我们新建一个名为HelloWorld2的工程,HelloWorld2.cpp的代码如下,程序上载后你就可以通过串口工具查看其运行效果,它会定时输出系统运行的时间:
#define DELAY_MS 500
DigitalOut led(LED1);
Serial pc(USBTX,USBRX);
int main() {
    pc.baud(115200);
    while (1)
    {
                        led=1;
                        wait_ms(DELAY_MS);
                        pc.printf("hello world,system had passed %d ms.\n",us_ticker_read());
                        led=0;
                        wait_ms(DELAY_MS);
    }
}



<
回复

使用道具 举报

61

主题

1071

回帖

17

蝴蝶豆

论坛元老

最后登录
2020-12-9
 楼主| 发表于 2016-10-23 21:50:06 | 显示全部楼层
占楼备用
回复 支持 反对

使用道具 举报

5

主题

100

回帖

0

蝴蝶豆

中级会员

最后登录
2017-5-27
发表于 2016-10-24 05:34:13 | 显示全部楼层
回复 支持 反对

使用道具 举报

4

主题

484

回帖

0

蝴蝶豆

金牌会员

最后登录
2020-8-12
发表于 2016-10-24 08:15:33 | 显示全部楼层
谢谢分享
回复 支持 反对

使用道具 举报

15

主题

145

回帖

5

蝴蝶豆

高级会员

最后登录
2019-9-19
发表于 2016-10-24 09:05:47 | 显示全部楼层
markmarkmarkmark
回复 支持 反对

使用道具 举报

9

主题

436

回帖

0

蝴蝶豆

金牌会员

最后登录
2019-9-20
发表于 2016-10-24 14:06:35 | 显示全部楼层
mark  good edit
回复 支持 反对

使用道具 举报

0

主题

159

回帖

0

蝴蝶豆

高级会员

最后登录
2017-3-9
发表于 2016-10-28 18:59:18 | 显示全部楼层
谢谢分享学习一下
回复 支持 反对

使用道具 举报

0

主题

5

回帖

0

蝴蝶豆

新手上路

最后登录
2018-3-22
发表于 2018-3-20 11:17:33 | 显示全部楼层
感谢分享,学习了
回复 支持 反对

使用道具 举报

0

主题

3

回帖

0

蝴蝶豆

新手上路

最后登录
2018-6-12
发表于 2018-6-12 17:14:24 | 显示全部楼层
好贴,谢谢分享
回复 支持 反对

使用道具 举报

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版