开通VIP,畅享免费电子书等14项超值服
首页
好书
留言交流
下载APP
联系客服
2020.10.07
C语言是一种函数型高级语言,嵌入式C程序是用用一条条指令构成函数,然后用函数组合起来构成程序。
1.main()函数:
每个C语言至少要有一个函数,也就是main()函数。main()函数是整个C语言程序的基础,是程序代码执行的起始点。所有其他函数是由main()函数直接或间接调用的。main()函数被认为是最低等级的任务,是系统启动程序时第一个被调用的函数。最简单的嵌入式C程序为:voidmain(){while(1)//;}嵌入式微控制器的应用程序一定包含一个无限循环,因为没有操作系统,任何时候都不允许执行完毕。C语言是一种无格式的语言,会忽略空白区域,除非被引号括起来。空白区域包括空格、Tab、换行(回车和换行)。
2.标识符:
标识符是变量或函数的名字,由字母或下划线开头,其后是由字母、数字或下划线构成的一个串。标识符通常区分大小写,编译器中#case指令可以用来控制是否区分大小写。标识符可以是任意长度,但一些编译器只识别有限长度的字符,例如前32位。一些特殊的字符串是编译器的保留字,有特定意义,不能作为标识符。保留字如下:
auto
default
for
int32
return
union
break
defined
goto
register
short
unsigned
bit
do
if
signed
void
byte
double
inline
sizeof
volatile
case
else
int
static
while
char
enum
int1
struct
const
extern
int8
long
switch
continue
float
int16
typedef
3.变量:
标准类型
编译器默认类型
比特数
取值范围
int1,shout
1
0,1
int8,int,signedchar,shortint
8
-128~+127
unsignedchar
unsignedint,unsignedchar
0~255
signedchar
int16,longint
16
-32768~32767
shortint
unsignedint
unsignedlongint
0~65535
signedint
longint
32
-2147483648~2147483647
unsignedint32
0~4294967295
signedlongint
signedint32
±1.175e-38~±3.402e38
4.常量:
BEL(beep)
‘\a’
‘\x07’
VT
‘\v’
‘\x0b’
Backspace
‘\b’
‘\x08’
FF
‘\f’
‘\x0c’
TAB
‘\t’
‘\x09’
CR
‘\r’
‘\x0d’
LF(newline)
‘\n’
‘\x0a’
因为反斜杠(\)和单引号(‘’)已被使用,字符输出时必须在前面加上反斜杠以免使编译器混淆。例如,’\’是一个单引号字符,’\\’是一个反斜杠字符。枚举,就是可列表表示的常量。用保留字enum用来将连续的整型常数值赋给一系列的标识符,例如:enum{start=10,next1,next2,end_val);
5.存储分类:
6.类型转换:
7.运算符的优先级:
运算符是表达式中的连接标识符,指示编译器要执行的类型操作。一个表达式中往往有多个运算符,其操作顺序依照优先级执行。
类别
级别
运算符
组合
基础
1(高)
()[]->
从左至右
一元
2
!~-(type)*&++--sizeof
从右至左
二元
3
*/%
算术
4
+-
移位
5
<<>>
关系
6
<<=>>==
相等性
7
==!=
位
&
9
^
10
|
逻辑
11
&&
12
||
条件
13
:
赋值
14(低)
=+=-=/=*=%=<<=>>=&=^=|=
8.函数:
9.指针:
10.数组:
11.函数的指针:
使用函数指针,可以让函数通过查询表操作的结果来调用。函数指针还可以让函数以引用的方式传递给其他函数。这可以用来创建一个动态的执行流程,有时也称“自修改”的代码。(*fp)();//执行fp所指向的函数Fp保存一个函数的入口地址。因为PIC单片机的栈空间有限,有些编译器不支持指向函数的指针。
12.结构:
13.共用体(联合):
14.typedef操作符:
15.位和位段:
16.sizeof操作符:
17.存储器类型:
longCCP_1;#byteCCP_10x15#byteCCP_1_LOW=0x15#byteCCP_1_HIGH=0x16longCCP_2;#byteCCP_20x1B#byteCCP_2_LOW=0x1B#byteCCP_2_HIGH=0x1C
18.预处理指令:
19.MPLABC30关键字对ANSIC的扩展:
模式
QI
HI
SI
DI
SF
DF
宽度/位
64
MPLABC30类型
longlong
longdouble
20.MPLABC30语句对ANSIC的扩展:
1)将标号作为值:可以用单目运算符“&&”获得当前函数(或包含函数)中定义的标号地址。值的类型为“void*”,且为常量,并可在这种类型的常量有效的任何地方使用这个值。例如:void*ptr;……ptr=&&foo;为使用这些值,需要能跳转到该值,可通过相对语句“goto*exp;”来实现。例如:goto*ptr;它可使用于“void*”类型的任何表达式。这些常量的一个用途是,用于初始化作为跳转表的静态数组。例如:staticvoid*array[]={&&foo,&&bar,&&hack};然后就可以通过索引来这样选择标号:goto*array[i];//并不检查下标是否超出范围这种标号值数组的用途与switch语句很类似,但switch语句更整齐,比数组更好。标号值的另外一个用途是在线程代码的解释程序中使用。解释程序函数中的标号可存储在线程代码中,用于快速调度。这种机制可能被错误使用而跳转到其他函数的代码中。编译器不能阻止这种现象的发生,因此必须小心,以确保目标地址对于当前函数有效。
2)省略操作数的条件表达式:条件表达式的中间操作数可以被省略。如果第一个操作数为非零,则其值就是条件表达式的值。因此,对于表达式:x:y如果x的值为非零,表达式的值就是x的值;否则,就是y的值。这个例子完全等同于:xx:y在这个简单的例子中,省略中间操作数并不是特别有用的。但当第一个操作数存在或者可能存在(如果它是一个宏参数)副作用时,省略中间操作数就会变得特别有用,因为重复中间操作数将产生两次副作用。省略中间操作数使用了已经计算过的值,避免了因重新计算而产生的不希望的影响。
3)case范围:可以在单个case标号中指定一个连续值的范围。例如:caselow...high:这与各个case标号使用的数字有相同的作用,每个数字对应从low到high中的每个整数值。这一功能对于指定ASCII字符码范围特别有用。例如:case‘A’...’z’:注:在“...”两边要留空格,否则与整数一起使用时可能出现解析错误。
21.MPLABC30对ANSIC表达式的扩展:
前面有0b或0B的一串二进制数字视为二进制整数。二进制数字由数字0和1组成。例如,十进制数字255可用二进制表示为0b11111111。像其他整型常量一样,二进制常量可以以字母u或U为后缀来指定为无符号型。二进制常量也可以以字母l或L为后缀,指定为长整型。类似地,后缀ll或LL表示双字整型的二进制常量。
22.MPLABC30支持的处理器:
dsPICC30支持的处理器如下表:
低端处理器
中端处理器
高端处理器
30F2010
30F3010
30F4011
30F5011
30F6010
30F2011
30F3011
30F4012
30F5013
30F6010A
30F2012
30F3012
30F4013
30F5015
30F6011
30F3013
30F5016
30F6011A
30F3014
30F6012
30F6012A
30F6013
30F6013A
30F6014
30F6014A
30F6015
23.MPLABC30支持的数据类型:
DsPICC30编译器支持8位、16位、32位和64位数据,所有多字节数据遵守的存储格式为低字节存储在低地址,高字节存储在高地址中,即一个数的低位字节存储在低地址的存储单元中。下表列出了dsPICC30支持的整型数据类型及对应的大小。
类型
最小值
最大值
char,signedchar
-128
127
0
255
short,signedshort
-32768
32767
unsignedshort
65535
int,signedint
long,signedlong
unsignedlong
longlong**,signedlonglong**
unsignedlonglong**
54
下表列出了dsPICC30支持的浮点型数据类型及对应的大小:
E最小值
E最大值
N最小值
N最大值
-126
2128
double*
-1022
1023
21024
24.MPLABC30的器件支持文件:
MPLABC30编译使用的器件支持文件主要有:处理器头文件、寄存器定义文件、使用特殊功能寄存器、使用宏和从C代码访问EEDATA。
2)寄存器定义文件:前述“处理器头文件”中描述的处理器头文件,指定了每个器件的所有SFR,但并未定义SFR的地址。Support/gld目录中有每个寄存器的链接描述文件,链接描述文件定义了SFR的地址。要使用链接描述文件,须指定链接器命令行选项:-Tp30fxxxx.gld其中,xxxx指器件的型号。假定有一个名为app2010.c的文件,它包含PIC30F2010器件的一个应用程序,则可使用下面的命令行编译和链接这个文件:pic30-gcc-oapp2010.o-Tp30f2010.gldapp2010.c其中,“-o”命令行选项命名输出COFF可执行文件,“-T”选项给出PIC30F2010器件的名称。如果在当前的目录中找不到p30f2010.gld,链接器将在已知的库路径中搜索。对于默认的安装,链接描述文件包含在PIC30_LIBRARAY_PATH中。
25.C语言的中断处理:
中断处理对于大多数单片机应用来说都是一个很重要的方面。中断用来使软件操作与实时发生的事件同步。当发生中断时,软件的正常执行流程被打断,并调用专门的函数来处理事件。当中断处理结束时,恢复先前的现场信息并继续正常执行流程。dsPIC30F器件支持多个内部和外部中断源,允许高优先级中断中断任何正在处理的低优先级中断。MPLABC30编译器完全支持在C或行内汇编代码中进行中断处理。
IRQ#
向量函数
主向量名
备用向量名
n/a
保留
_ReservedTrap0
_AltReservedTrap0
振荡器失效陷阱
_OscillatorFail
_AltOscillatorFail
地址错误陷阱
_AddressError
_AltAddressError
堆栈错误陷阱
_StackError
_AltStackError
数学错误陷阱
_MathError
_AltMathError
_ReservedTrap5
_AltReservedTrap5
_ReservedTrap6
_AltReservedTrap6
_ReservedTrap7
_AltReservedTrap7
INT0(外部中断0)
_INT0Interrupt
_AltINT0Interrupt
IC1(输入捕捉1)
_IC1Interrupt
_AltIC1Interrupt
OC1(输出比较1)
_OC1Interrupt
_AltOC1Interrupt
TMR1(定时器1)
_T1Interrupt
_AltT1Interrupt
IC2(输入捕捉2)
_IC2Interrupt
_AltIC2Interrupt
OC2(输出比较2)
_OC2Interrupt
_AltOC2Interrupt
TMR2(定时器2)
_T2Interrupt
_AltT2Interrupt
TMR3(定时器3)
_T3Interrupt
_AltT3Interrupt
SPI1(串行外设接口1)
_SPI1Interrupt
_AltSPI1Interrupt
UART1RX(UART1接收器)
_U1RXInterrupt
_AltU1RXInterrupt
UART1TX(UART1发送器)
_U1TXInterrupt
_AltU1TXInterrupt
ADC(ADC转换完成)
_ADCInterrupt
_AltADCInterrupt
NVM(NVM写完成)
_NVMInterrupt
_AltNVMInterrupt
从I2C中断
_SI2CInterrupt
_AltSI2CInterrupt
14
主I2C中断
_MI2CInterrupt
_AltMI2CInterrupt
15
CN(输入变化中断)
_CNInterrupt
_AltCNInterrupt
INT1(外部中断1)
_INT1Interrupt
_AltINT1Interrupt
17
IC7(输入捕捉7)
_IC7Interrupt
_AltIC7Interrupt
18
IC8(输入捕捉8)
_IC8Interrupt
_AltIC8Interrupt
19
OC3(输出比较3)
_OC3Interrupt
_AltOC3Interrupt
20
OC4(输出比较4)
_OC4Interrupt
_AltOC4Interrupt
21
TMR4(定时器4)
_T4Interrupt
_AltT4Interrupt
22
TMR5(定时器5)
_T5Interrupt
_AltT5Interrupt
23
INT2(外部中断2)
_INT2Interrupt
_AltINT2Interrupt
24
UART2RX(UART1接收器)
_U2RXInterrupt
_AltU2RXInterrupt
25
UART2TX(UART1发送器)
_U2TXInterrupt
_AltU2TXInterrupt
26
SPI2(串行外设接口2)
_SPI2Interrupt
_AltSPI2Interrupt
27
CAN1(组合IRQ)
_C1Interrupt
_AltC1Interrupt
28
IC3(输入捕捉3)
_IC3Interrupt
_AltIC3Interrupt
29
IC4(输入捕捉4)
_IC4Interrupt
_AltIC4Interrupt
30
IC5(输入捕捉5)
_IC5Interrupt
_AltIC5Interrupt
31
IC6(输入捕捉7)
_IC6Interrupt
_AltIC6Interrupt
OC5(输出比较5)
_OC5Interrupt
_AltOC5Interrupt
33
OC6(输出比较6)
_OC6Interrupt
_AltOC6Interrupt
34
OC7(输出比较7)
_OC7Interrupt
_AltOC7Interrupt
35
OC8(输出比较8)
_OC8Interrupt
_AltOC8Interrupt
36
INT3(外部中断3)
_INT3Interrupt
_AltINT3Interrupt
37
INT4(外部中断4)
_INT4Interrupt
_AltINT4Interrupt
38
CAN2(组合IRQ)
_C2Interrupt
_AltC2Interrupt
39
PWM(PWM周期匹配)
_PWMInterrupt
_AltPWMInterrupt
40
QEI(位置计数器比较)
_QEIInterrupt
_AltQEIInterrupt
41
DCI(CODEC传输完成)
_DCIInterrupt
_AltDCIInterrupt
42
PLVD(低电压检测)
_LVDInterrupt
_AltLVDInterrupt
43
FLTA(MPWM故障A)
_FLTAInterrupt
_AltFLTAInterrupt
44
FLTB(MPWM故障B)
_FLTBInterrupt
_AltFLTBInterrupt
45
_Interrupt45
_AltInterrupt45
46
_Interrupt46
_AltInterrupt46
47
_Interrupt47
_AltInterrupt47
48
_Interrupt48
_AltInterrupt48
49
_Interrupt49
_AltInterrupt49
50
_Interrupt50
_AltInterrupt50
51
_Interrupt51
_AltInterrupt51
52
_Interrupt52
_AltInterrupt52
53
_Interrupt53
_AltInterrupt53
3)中断服务程序现场保护:为了保证从中断返回到代码后,条件状态与中断前相同,必须保护特定寄存器的现场信息。中断,就其本质来说,会在不可预测的时刻发生。因此,被中断的代码必须能以与中断发生时相同的机器状态继续运行。为了正确处理中断返回,中断函数的设置(prologue)代码在堆栈中自动保护编译器管理的工作寄存器和特殊功能寄存器,以便在ISR末尾恢复这些寄存器内容。可使用interrupt属性值,可选的save参数指定要保护和恢复的其他变量和特殊功能寄存器。在某些应用中,可能需要在中断服务程序内,在编译器生成的prologue函数前,插入汇编语句。例如,在中断服务程序的入口可能需要递增一个信号,可以这样来实现:void__attribute__((__interrupt__(__preprologue__(“inc_semaphore”))))MyAltIRQ(void);
5)中断嵌套:MPLABC30支持中断嵌套,dsPIC器件支持中断嵌套。在ISR中,将处理器资源保存在堆栈中,对嵌套ISR的编码与非嵌套中断的编码相同。通过清零INTCON1寄存器中的NSTDIS位(中断嵌套禁止位)来使能中断嵌套。(dsPIC复位时是使能嵌套中断的,是默认设置。)在中断优先级控制寄存器(IPCn)中,为每个中断源分配了一个优先级。如果有一个处于等待状态的中断请求(IRQ),其优先级等于或高于处理器状态寄存器中的(ST寄存器中的CPUPRI字段)当前处理器优先级,处理器将响应中断。