合泰单片机C语言教程
单片机c语言教程
单片机c语言教程单片机(Microcontroller)是一种集成电路芯片,内部包含了处理器、存储器、输入/输出端口以及其他辅助设备,可以完成各种控制、计算和通信任务。
单片机广泛应用于嵌入式系统中,是实现各种电子设备的核心部件。
C语言是一种通用的高级编程语言,具有结构化和模块化的特点,易于学习和实践。
在单片机编程中,C语言往往是首选的编程语言,因为它能够提供许多便利的程序开发和调试工具。
单片机C语言教程对于初学者来说非常重要。
首先,教程介绍了C语言的基础知识,如变量、数据类型、运算符等。
这些知识是理解和编写C语言程序的基础。
接着,教程会详细介绍C语言的控制结构,如条件语句、循环语句和选择语句等。
这些结构对于实现单片机控制逻辑非常重要。
除了基础知识,单片机C语言教程还会介绍如何使用C语言编写单片机的输入/输出程序。
单片机的输入/输出是与外部设备进行交互的关键部分。
教程会介绍如何使用C语言读取和写入单片机的输入/输出端口,控制外部设备的状态。
此外,教程还会介绍C语言中的位操作,以及如何通过位操作实现对单片机的灵活控制。
单片机C语言教程还会介绍如何使用C语言编写中断服务程序。
中断是单片机处理外部事件的重要机制,可以实现实时响应和高效处理。
教程会详细讲解中断的原理和使用方法,以及如何在C语言中编写中断服务程序。
最后,单片机C语言教程还会介绍如何使用C语言进行调试和优化。
调试是程序开发中不可或缺的环节,可以帮助我们找出程序中的错误和问题。
教程会介绍如何使用调试工具和技术来调试单片机的C语言程序。
此外,教程还会介绍一些优化技巧,以提高单片机程序的运行效率和响应速度。
总之,单片机C语言教程是学习和应用单片机的关键资料。
通过学习教程,我们可以了解C语言的基础知识、控制结构、输入/输出编程、中断编程以及调试和优化技巧。
这些知识将帮助我们更好地理解和应用单片机,实现各种电子设备的功能和控制。
合泰单片机教程
合泰单片机教程介绍:合泰单片机(简称HT单片机)是一种基于汇编语言和C语言的微型控制器。
它使用了16位的指令集,并集成了丰富的外设接口,使得它成为嵌入式系统开发的理想选择。
本文将为你提供一份合泰单片机的入门教程,帮助你了解其基本知识和应用。
一、单片机的基本概念1.1 单片机的定义单片机是一种集成了微型计算机的所有核心部件(如处理器、内存、IO接口等)的电子器件。
它通常用于控制和管理嵌入式系统的各种任务。
1.2 单片机的组成单片机主要由中央处理器(CPU)、存储器和输入输出(IO)端口组成。
其中,中央处理器用于处理数据和执行指令,存储器用于存放程序和数据,输入输出端口用于与外部设备进行通信。
1.3 单片机的应用单片机广泛应用于家电、汽车、电子设备、仪器仪表、工业自动化和物联网等领域。
它可以实现各种功能,如温度控制、机器人控制、数据采集、显示控制等。
二、合泰单片机的特点2.1 高性能合泰单片机采用16位指令集,具有较高的运算速度和处理能力。
它的工作频率可以达到20MHz,适合处理多种复杂的任务。
2.2 丰富的外设接口合泰单片机集成了多个外设接口,如UART串口、定时器、PWM输出、模拟输入、数字输入输出等,可以满足各种应用的需求。
2.3 低功耗设计合泰单片机采用先进的低功耗设计,具有快速唤醒和休眠功能,可以节省电能,延长电池寿命。
2.4 易用性合泰单片机具有友好的开发环境和丰富的开发工具,可以快速编写和调试程序。
同时,它还支持多种编程语言,如汇编语言和C语言。
三、合泰单片机的编程3.1 汇编语言编程汇编语言是一种底层语言,直接与单片机的寄存器和指令进行交互。
通过汇编语言,可以对单片机进行精确的控制和编程。
3.2 C语言编程C语言是一种高级语言,它提供了丰富的库函数和语法结构,使得程序开发更加快捷和便利。
合泰单片机提供了C语言的开发环境和库函数,方便开发者进行项目开发。
3.3 编程实例下面是一个使用C语言编写的LED闪烁的实例代码:```c#include <htc.h>#define _XTAL_FREQ 20000000void main(){TRISA = 0x00; //将端口A设置为输出while(1){PORTA = 0xFF; //点亮LED__delay_ms(1000); //延时1秒PORTA = 0x00; //关闭LED__delay_ms(1000); //延时1秒}}```这个实例代码使用了合泰单片机的GPIO接口控制LED的亮灭,通过循环和延时函数实现了LED的闪烁效果。
单片机c语言编写流程
单片机c语言编写流程下载温馨提示:该文档是我店铺精心编制而成,希望大家下载以后,能够帮助大家解决实际的问题。
文档下载后可定制随意修改,请根据实际需要进行相应的调整和使用,谢谢!并且,本店铺为大家提供各种各样类型的实用资料,如教育随笔、日记赏析、句子摘抄、古诗大全、经典美文、话题作文、工作总结、词语解析、文案摘录、其他资料等等,如想了解不同资料格式和写法,敬请关注!Download tips: This document is carefully compiled by theeditor. I hope that after you download them,they can help yousolve practical problems. The document can be customized andmodified after downloading,please adjust and use it according toactual needs, thank you!In addition, our shop provides you with various types ofpractical materials,such as educational essays, diaryappreciation,sentence excerpts,ancient poems,classic articles,topic composition,work summary,word parsing,copy excerpts,other materials and so on,want to know different data formats andwriting methods,please pay attention!1. 确定需求:明确你要实现的功能和任务,例如控制外部设备、处理传感器数据、实现通信等。
合泰C语言用户手册
函数 ....................................................................................................27
数组 ....................................................................................................28
位数据类型 ........................................................................................25
内嵌式汇编语言 ................................................................................26
指针与数组 ................................................................................................17
指针 ....................................................................................................17
数组 ....................................................................................................17
结构体与共用体(Structures and Unions) ..................................................18
单片机c语言教程pdf版
单片机c语言教程pdf版标题:单片机C语言教程PDF版引言概述:单片机是一种集成电路,具备处理和控制功能,广泛应用于各个领域。
而C语言是单片机编程的重要基础,掌握C语言对于学习和应用单片机至关重要。
本文将介绍一本单片机C语言教程的PDF版本,内容详实且专业,有助于读者学习和掌握单片机编程。
正文内容:1. 引言1.1 单片机的基本概念1.2 C语言在单片机编程中的重要性2. 单片机C语言教程PDF版的特点2.1 详细的基础知识讲解2.2 实例驱动的学习方法2.3 丰富的实践项目案例3. 单片机C语言教程PDF版的内容3.1 C语言基础语法3.1.1 变量和数据类型3.1.2 控制结构和循环3.1.3 函数和指针3.2 单片机的基本概念和架构3.2.1 单片机的组成和工作原理3.2.2 寄存器和IO口的使用3.2.3 中断和定时器的应用3.3 单片机编程实践3.3.1 LED灯控制3.3.2 数码管显示3.3.3 按键输入和中断控制3.4 进阶应用3.4.1 ADC和DAC的使用3.4.2 串口通信3.4.3 蓝牙和WiFi模块的应用4. 单片机C语言教程PDF版的优势4.1 方便的学习和查阅4.2 适合初学者和进阶者4.3 丰富的实践案例5. 总结5.1 单片机C语言教程PDF版提供了系统而全面的单片机编程知识5.2 通过学习该教程,读者能够掌握C语言和单片机编程的基础和应用5.3 该教程的实践案例能够帮助读者深入理解和应用所学知识总结:单片机C语言教程PDF版是一本内容丰富、专业详实的教程,涵盖了单片机和C语言的基础知识、编程实践和进阶应用。
通过学习该教程,读者能够全面掌握单片机编程所需的知识和技能。
该教程的优势在于方便的学习和查阅方式,适合初学者和进阶者,且提供了丰富的实践案例,帮助读者深入理解和应用所学知识。
单片机c语言教程
单片机c语言教程单片机(Microcontroller)是一种使用在嵌入式系统中的计算机芯片。
它集成了处理器、内存、外设接口以及其他功能模块,可以作为控制系统的核心部分。
C语言是一种高级编程语言,广泛应用于单片机编程中。
本教程将为初学者介绍单片机C语言的基础知识和编程技巧。
一、单片机概述单片机是一种微型计算机,具有处理器、存储器和输入输出设备等功能模块,用于控制各种电子设备。
单片机通常包含CPU、存储器和外设接口三个主要部分。
它的特点是体积小、功耗低、功能强大,适合各种嵌入式应用场景。
二、C语言基础1. 数据类型在C语言中,我们需要了解不同的数据类型来存储和操作不同种类的数据。
常用的数据类型包括整型(int)、字符型(char)、浮点型(float)等。
2. 变量和常量变量用于存储数据,而常量则代表固定的数值或字符。
在编写单片机程序时,我们需要声明变量和常量,并进行相应的赋值操作。
3. 运算符和表达式C语言提供了多种运算符,如算术运算符、逻辑运算符和关系运算符等。
通过表达式的组合,我们可以实现各种复杂的计算和判断逻辑。
4. 控制语句编写单片机程序时,控制语句可以控制程序的执行流程。
常用的控制语句包括条件语句(if-else)、循环语句(for、while)和跳转语句(break、continue)等。
三、单片机编程环境搭建1. 安装开发软件为了编写和调试单片机程序,我们需要安装相应的开发软件,如Keil C51、MPLAB X等。
这些软件提供了集成的开发环境,可以简化编程过程。
2. 单片机选择和连接根据项目需求,选择合适的单片机型号,并通过编程器将单片机与计算机连接起来。
这样,我们就可以将编写好的程序下载到单片机中进行运行。
四、单片机C语言编程实践1. 点亮LED灯LED是最基础的外设之一,我们可以通过单片机的IO口控制LED的亮灭。
通过编写C语言程序,将IO口设置为输出,可以实现点亮和熄灭LED的功能。
合泰单片机iic例程
SCL=1;
Nop(); //起始条件建立时间大于4.7us,延时
Nop();
Nop();
Nop();
Nop();
SDA=0; //发送起始信号
Nop(); //起始条件锁定时间大于4μs
Nop();
Nop();
Nop();
Nop();
Nop();
for(BitCnt=0;BitCnt<8;BitCnt++) //要传送的数据长度为8位
{
if(c&0x80) SDA=1; //判断发送位
else SDA=0;
c<<=1;
Nop();
SCL=1; //置时钟线为高,通知被控器开始接收数据位
Nop();
SCL=1;
SDAIn();
Nop();
Nop();
Nop();
if(SDA==1) ack=0;
else ack=1; //判断是否接收到应答信号
SCL=0;
Nop();
Nop();
}
uint8 RcvByte()
{
uint8 retc;
{
uint8 i;
StartI2c(); //启动总线
SendByte(sla); //发送器件地址
if(ack==0)return(0);
for(i=0;i<subano;i++)
{
SendByte(*subaturn(0);
#define SCLC _pac1 //时钟线控制端
#define SDAIn() SDAC=1 //输入
Holtek C语言学习教程
第一课时1、Holtek公司编译器HT-IDE3000使用说明(1)双击打开HT-IDE3000,进入编译器的界面,见下图:(2)单击“工程”——>选择“新建”,弹出下图窗口;——Project Name:新建项目文件的名称,不建议使用中文名称;——Project Location:项目文件存放的位置,勾选“Create directory for project”后,会自动建立一个文件夹,项目文件都存放在此文件夹内;——Project MCU:单片机的型号;——Choose Language Tool:选择编程语言,这里选择“V2”版本的C语言。
(3)点击下一步,选择“.C”;(4)点击下一步,再点击下一步,点击OK,然后弹出“配置选项”,配置选择只要是对单片机一些功能和特性进行设置,例如工作电压,工作频率,看门狗等;(5)配置选项设置完后,点击OK,再点击确定,那么新的工程就建立完毕了。
2、C语言程序设计(1)主函数每个程序只有一个主函数,程序是从主函数开始执行。
格式:void main(){}例子:#include "HT66F40.h"void main()//程序从这里开始跑{_nop();//语句1_nop();//语句2_nop();//语句3}功能说明:程序执行的顺序,语句1—>语句2—>语句3。
(2)子函数一个程序包含各种功能,如果每种功能都做成一个子函数,那么整个程序的架构实现了模块化。
例如,LCD的开启,显示及关闭这三个功能可以分别做成三个独立的子函数。
使用子函数的步骤:①编写子函数的功能void TurnOn_LCD()//LCD开启子函数,TurnOn_LCD是函数的名称{_nop();//这里先用空指令代表子函数的功能_nop();//这里先用空指令代表子函数的功能}②声明子函数,告诉单片机有这个子函数存在void TurnOn_LCD();技巧:直接把步骤①的第一行复制过来,然后在后面加上分号;③调用子函数TurnOn_LCD();例子:#include "HT66F40.h"void TurnOn_LCD();//声明子函数,告诉单片机有这个子函数存在void TurnOff_LCD();//声明子函数,告诉单片机有这个子函数存在void display_LCD();//声明子函数,告诉单片机有这个子函数存在void main(){_nop();//空指令_nop();//空指令_nop();//空指令while(1) //while循环结构,当小括号里内容为真,执行{//while大括号里的内容TurnOn_LCD(); //调用LCD开启子函数display_LCD();//调用LCD显示子函数TurnOff_LCD();//调用LCD关闭子函数}}void TurnOn_LCD()//编写子函数的功能,LCD开启子函数,TurnOn_LCD是{ //函数的名称_nop();//这里先用空指令代表子函数的功能_nop();//这里先用空指令代表子函数的功能}void TurnOff_LCD()//编写子函数的功能,LCD关闭子函数,TurnOff_LCD是{//函数的名称_nop();//这里先用空指令代表子函数的功能_nop();//这里先用空指令代表子函数的功能}void display_LCD()//编写子函数的功能,LCD显示子函数,display_LCD是{//函数的名称_nop();//这里先用空指令代表子函数的功能_nop();//这里先用空指令代表子函数的功能}(3)中断子函数使用中断子函数的步骤:①相关寄存器进行初始化(请查阅相关型号IC的PDF)②声明中断子函数地址格式:#pragma vector 中断子函数名称@中断入口地址例如:#pragma vector isr_tm0@0x14③编写中断子函数的功能例如:void isr_tm0(){}例子:#include "HT66F40.h"#pragma vector isr_tm0 @0x14//声明中断子函数的入口地址void mcu_init();//声明单片机初始化子函数void main(){mcu_init();while(1)//while循环结构,当小括号里内容为真,执行while{//大括号里的内容_nop();_nop();}}void isr_tm0()//编写中断子函数的功能{_t0af=0;//清除中断标志位_nop();//这里先用空指令代表中断子函数的功能}void mcu_init()//编写单片机初始化子函数{//定时器相关寄存器初始化_tm0c0=0b00000000;//定时器计数时钟fsys/4=1Mhz,fsys=4Mhz为系统//频率_tm0c1=0b11000001;//选择定时计数工作模式,//清0计数器的条件:与比较器A匹配,即//计数值与tm0al,tm0ah的值相等时,计数器清0)_tm0al=0xe8;//0x03e8=1000_tm0ah=0x03;_t0on=1;//启动定时器//定时器中断相关寄存器初始化_emi=1;//总中断控制位,0-关闭1-开启_mf0e=1;//多功能中断0控制位,0-关闭1-开启_t0ae=1;//TM0比较器A匹配中断控制位,0-关闭1-开启}(4)函数的返回值及参数的介绍①无返回值,无参数函数:前面介绍的函数均为无返回值无参数函数。
经典:合泰指令教学
A,[m] ; ACC与数据存储器做“或”运算,结果放入数据存储
A,[m] ; ACC与数据存储器做“异或”运算,结果放入数据存
A, x A, x A, x [m] [m]
;ACC与立即数做“与”运算,结果放入ACC ;ACC与立即数做“或”运算,结果放入ACC ;ACC与立即数做“异或”运算,结果放入ACC ;对数据存储器取反,结果放入数据存储器 ;对数据存储器取反,结果放入ACC
10
递增和递减
INCA INC
存储器 DECA DEC
存储器
[m] ;递增数据存储器,结果放入ACC [m] ; 递增数据存储器,结果放入数据
[m] ;递减数据存储器,结果放入ACC [m] ; 递减数据存储器,结果放入数据
11
移位
RRA RR RRCA RRC
存储器 RLA RL RLCA RLC
单片机指令概述
合泰单片机指令运用
了解指令,让编程序变得更容 易.
1
什么是单片机
单片机就是一块单片的计算机看起来就是一个黑块,他把计算机正常工 作所需要用的设备接口等全部集成在一个芯片上,并可以完成一些简 单的工作,这里举一个简单的例子让你了解单片机是什么是干什么功 能的,比如说你现在把一个led小灯,接在了单片机的P1.0引脚上,我 们要灯亮就给单片机一个setb P1.0的指令,我们要灯熄灭就给clr p1.0 灯就熄了。
3
单片机的应用场合
◆智能仪器仪表 单片机用于各种仪器仪表,一方面提高了仪器仪表的使用功能和精度,使仪器仪表智
能化,同时还简化了仪器仪表的硬件结构,从而可以方便地完成仪器仪表产品的升级换 代。如各种智能电气测量仪表、智能传感器等。 机电一体化产品是集机械技术、微电子技术、自动化技术和计算机技术于一体,具有 智能化特征的各种机电产品。单片机在机电一体化产品的开发中可以发挥巨大的作用。 典型产品如机器人、数控机床、自动包装机、点钞机、医疗设备、打印机、传真机、复 印机等。 ◆实时工业控制 单片机还可以用于各种物理量的采集与控制。电流、电压、温度、液位、流量等物理 参数的采集和控制均可以利用单片机方便地实现。在这类系统中,利用单片机作为系统 控制器,可以根据被控对象的不同特征采用不同的智能算法,实现期望的控制指标,从 而提高生产效率和产品质量。典型应用如电机转速控制、温度控制、自动生产线等 。 ◆家用电器 家用电器是单片机的又一重要应用领域,前景十分广阔。如空调器、电冰箱、洗衣机、 电饭煲、高档洗浴设备、高档玩具等。 另外,在交通领域中,汽车、火车、飞机、航天器等均有单片机 的广泛应用。如汽车 自动驾驶系统、航天测控系统、黑匣子还有分 布式系统的前端模块等等 。
单片机C语言入门教程
单片机C语言入门教程一、简介在现代电子技术领域中,单片机是一种关键的组成部分。
而C语言是一种强大的编程语言,被广泛应用于单片机开发中。
本教程旨在帮助读者快速入门单片机C语言编程。
二、C语言概述C语言是一种面向过程的编程语言,它结合了高级语言和汇编语言的特点。
C语言具有简洁、灵活和可移植的特点,非常适合单片机开发。
三、环境搭建在进行单片机C语言编程之前,我们需要搭建开发环境。
首先,我们需要选择一款合适的集成开发环境(IDE),例如Keil、IAR等。
然后,安装相应的编译器和调试工具。
最后,连接硬件设备并配置相应的开发板。
四、C语言基础1. 变量和数据类型:在C语言中,我们需要先声明变量并指定数据类型,然后才能进行相应的操作。
C语言中常用的数据类型包括整型、浮点型、字符型等。
2. 运算符和表达式:C语言支持多种运算符,包括算术运算符、赋值运算符、比较运算符等。
通过运算符和表达式的组合,我们可以实现各种复杂的逻辑操作。
3. 控制语句:控制语句用于控制程序的流程,常见的控制语句包括条件语句、循环语句和跳转语句。
通过合理使用这些语句,我们可以实现程序的灵活控制。
五、单片机编程基础1. 引脚配置:在进行单片机开发时,我们需要配置相应的引脚功能,包括输入、输出、中断等。
通过合理配置引脚,我们可以与外部设备进行交互。
2. 中断编程:中断是一种常用的单片机编程技术,它可以在特定的事件发生时,立即中断当前程序的执行,转而去处理中断服务程序。
通过合理使用中断,我们可以实现实时响应和处理外部事件。
3. 定时器编程:定时器是单片机中重要的计时功能模块,它可以用来生成精确的时间延时、产生周期性的定时事件等。
通过合理利用定时器,我们可以实现各种时间相关的功能。
六、案例实践在学习了C语言的基础知识和单片机编程技巧后,我们可以通过一些实践案例来加深对知识的理解和应用。
例如,通过控制LED灯的亮度或者控制舵机的角度等实践,来巩固所学内容。
单片机c语言教程pdf版
单片机c语言教程pdf版单片机是指由一个集成电路芯片组成的完整的微型计算机系统,可用于各种嵌入式应用中。
而C语言是一种高级编程语言,具有灵活、强大和易于学习的特点。
本教程将介绍如何在单片机上使用C语言进行编程,并提供PDF版本的教程供读者下载学习。
第一节:单片机基础知识在开始学习单片机的C语言编程之前,我们需要了解一些基础知识。
首先,单片机是由中央处理器(CPU)、存储器和输入输出端口组成的。
其中,CPU负责处理计算和控制指令,存储器用于存储程序和数据,输入输出端口用于与外部设备进行通信。
第二节:C语言入门C语言是一种通用的高级编程语言,广泛应用于各种领域。
在学习单片机的C语言编程之前,首先需要了解C语言的基本语法和常用编程技巧。
这包括变量和数据类型、运算符、条件语句、循环语句等。
第三节:单片机开发环境的搭建在进行单片机的C语言编程之前,我们需要搭建相应的开发环境。
通常,单片机的开发环境包括硬件平台和软件工具。
硬件平台可以是一块开发板,软件工具可以是一款集成开发环境(IDE)。
第四节:C语言在单片机中的应用C语言在单片机中的应用非常广泛。
通过C语言,我们可以编写各种功能丰富的程序,如LED灯控制、温度传感器读取、蜂鸣器控制等。
在这一节中,我们将介绍如何使用C语言在单片机中实现这些功能。
第五节:单片机项目实战在学习了前面的知识后,我们将进行一个单片机项目实战。
通过实践,我们可以更好地理解并应用所学的知识。
本节将介绍一个具体的项目,如小车避障控制,通过编写C语言程序来实现这一功能。
第六节:扩展学习资料除了本教程外,还有许多其他的学习资料可供参考。
这些资料包括单片机的相关书籍、在线视频教程、论坛等资源。
本节将为读者提供一些推荐的扩展学习资料,并提供PDF版本供下载。
结语:本教程介绍了单片机C语言编程的基础知识和实践应用。
通过学习本教程,读者可以了解到单片机的基本原理和C语言的编程技巧,并能够独立进行简单的单片机项目开发。
单片机C语言教程(二)
单片机C语言教程(二)引言:本文将为读者提供一个关于单片机C语言的教程,旨在帮助读者更加深入地理解和掌握此编程语言在单片机开发中的应用。
本教程将首先介绍C语言在单片机编程中的基础知识,然后深入讲解其在输入输出、控制结构、函数和指针等方面的应用。
通过学习本教程,读者将能够掌握单片机C语言的编程技巧,并能够运用于实际开发中。
一、C语言在单片机编程中的基础知识1. 数据类型:介绍单片机C语言中的基本数据类型,如整型、浮点型和字符型等。
2. 变量和常量:探讨单片机C语言中的变量和常量的定义和使用。
3. 运算符:介绍单片机C语言中常用的运算符,并详细解释其使用方法。
4. 数组和字符串:讲解单片机C语言中数组和字符串的定义与应用,以及相关的操作方法。
5. 输入输出:探讨单片机C语言中输入和输出的方法,包括标准输入输出函数的使用和文件的读写操作。
二、C语言在单片机编程中的控制结构1. 顺序结构:介绍单片机C语言中顺序结构的概念和使用方法。
2. 条件结构:讲解单片机C语言中的条件结构,如if语句、switch语句等,并给出实例演示。
3. 循环结构:详细介绍单片机C语言中循环结构的三种常见形式:while循环、do-while循环和for循环,并进行比较和实例化操作。
4. 跳转结构:讲解单片机C语言中的跳转结构,如break语句、continue语句和goto语句等,并给出应用案例。
5. 多重控制结构:探讨单片机C语言中多重控制结构的应用,如嵌套循环、嵌套条件等,并给出实例说明。
三、C语言在单片机编程中的函数1. 函数定义与声明:介绍单片机C语言中函数的定义和声明,以及函数的返回类型、参数等内容。
2. 函数调用和返回:详细讲解单片机C语言中函数的调用和返回的各种情况及参数传递的方式。
3. 内联函数:探讨单片机C语言中的内联函数概念,以及其与普通函数的区别和使用方法。
4. 递归函数:介绍单片机C语言中递归函数的概念和应用场景,并给出实例讲解。
合泰单片机C语言教程讲解
Holtek 微控制器應用範例–使用Holtek C 語言目錄第一章內容簡介第二章選定Holtek C 語言的使用環境2.1 進入HT-IDE3000 建立新的專案時, 選定Holtek C 編譯器2.2 已開啟專案後, 選用Holtek C 編譯器第三章微控制器C 語言程式的速成3.1 定義主函式main()3.2定義副函式(sub-function)3.3定義全域變數(global variable)3.4定義中斷服務函式(Interrupt Service Routine : ISR)3.5 其他第四章 C 語言程式4.1 C 程式架構4.2 開始用C 語言設計一個程式4.2.1 定義主函式main4.2.2 將標頭檔引入(include a header file)4.2.3 定義文字符號及變數4.2.4 設定微控制器及裝置的初始狀態4.2.5 設計子函式4.2.6 設計中斷服務函式4.3變數(variable) 及資料型態(data type)4.3.1 變數名4.3.2 資料型態4.3.3 變數的有效範圍(scope)4.3.4 變數的資料型態(data type)整數型(integer)浮點型(floating point)4.3.5 bit 資料型態4.3.6儲存類別(storage class) 與修飾詞(qualifier)儲存類別(storage class)修飾詞(qualifier)4.3.7絕對變數(absolute variable)4.3.8常數(constant)4.3.9指標(pointer) 與陣列(array)指標的運算子& 與*陣列(array)4.3.10結構(struct) 與等位(union)結構的運算子-> 與.4.4運算子(Operators)運算前的型態轉換4.5程式流程控制(program flow control)4.5.1if-else 敘述4.5.2switch 敘述4.5.3for 敘述4.5.4while 敘述4.5.5do-while 敘述4.5.6goto 敘述4.5.7break 與continue 敘述4.6函式(Functions)4.6.1參數(arguments)4.6.2返回值(return values)4.7中斷服務函式(Interrupt Service Routines)4.8在C 語言程式中嵌入組合語言(in-line assembly code)從組合語言的程式去存取 C 語言的物件(變數)4.9前置處理指令(Preprocessor)4.9.1 定義文字符號(#define)4.9.2引入檔案(#include)4.9.3內嵌組合語言(inline assembly)4.9.4 條件式編譯(#if/#endif)4.9.5 編譯器的特殊選項pragma4.10Holtek C 編譯器的內建函式(built-in functions)第五章基本 C 語言程式5.1 語法觀念5.2 迴圈的應用(loop)5.3 撰寫MCU 應用程式的注意事項5.4 可供微控制器應用程式使用的範本5.5 設計微控制器應用程式的小技巧第六章程式範例–初級6.1LED 跑馬燈6.2LED 霹靂燈6.3 單顆七段顯示器6.4 5*5 點矩陣LED 顯示6.5 HT48 微控制器控制HT1621 LCD 的顯示6.6 HT48 微控制器控制LCD 模組的顯示6.7 具LCD 驅動功能的微控制器之顯示應用程式– HT46R636.8 顯示器的通用函式– HT44780 LCM6.9 鍵盤掃描程式第七章程式範例–中斷函式7.1 用時鐘控制LED 的亮與滅7.2 類比/數位轉換(ADC) 的應用第八章HT46R52A 應用於鎳氫電池充電器(HA0084T)第九章程式範例– HT46R74D-1 胎壓計(HA0105T)第一章內容簡介盛群半導體公司(Holtek)開發一系列的八位元微控制器(micro-controller, MCU). 當開發微控制器的應用程式時, 除了可使用盛群提供的組合語言(assembly language),也可使用標準的C 語言編譯器(C compiler).由於八位元微控制器的記憶體空間, 不論是程式記憶體(program memory space)或是資料記憶體(ram memory space), 皆是有限制的, 通常會使用組合語言開發應用程式. 但是越來越多的微控制器支援更多的記憶體以及更多的功能, 使得程式也相對的擴大. 如果仍然使用組合語言開發程式, 不但費時費力, 未來在維護及擴增功能的工作上也相當困難.因此, 使用高階程式語言, 例如C 語言, 來開發應用程式就是一種可行的趨勢.C 語言是高階程式語言中的一種, 它具有高度的的可讀性及可移植性(portability),除了能夠快速地完成應用程式的開發與偵錯, 也很容易移植到其他的微控制器上. 當程式需要縮減或擴充功能時, 也很容易的完成, 因此很適合於微控制器的程式開發.本書主要是以Holtek C 語言為主, 說明如何使用Holtek C 語言撰寫盛群微控制器的應用程式, 包括 C 的程式架構, C 語言的一般用法, 特殊用法及應用範例書中將說明在開發微控制器的應用程式時需要注意的地方及如何撰寫會比較恰當, 並配以實例解釋.讀者可以參考修改或直接採用到自己的程式中, 再用發展工具HT-ICE, HT-IDE3000 驗證之.第二章介紹選用Holtek C 編譯器的步驟, 指引HT-IDE3000 呼叫Holtek C 編譯器去編譯C 語言的原始程式.第三章提供一種快速撰寫 C 程式的方法, 對ANSI C 語言熟悉的用者, 可於閱讀本章之後即開始撰寫微控制器的 C 語言程式第四章介紹C 語言, 未曾使用過 C 語言的讀者應仔細閱讀本章以了解 C 語言的用法第五章介紹使用 C 語言寫程式的基本觀念, 注意事項及建議的寫作方法第六章到第九章則是應用範例, 針對盛群各系列的微控制器, 以 C 語言撰寫的應用程式. 包含有功能說明, 應用電路及程式說明.文件編號版別 1.20日期2008/5/26 第5 頁共189 頁第二章選定Holtek C 編譯器的使用環境2.1 進入HT-IDE3000, 建立新的專案時, 選定Holtek C 編譯器進入HT-IDE3000 開發環境後, 依照下列方法建立一個新的專案(project)→ 移動滑鼠游標到Project 選單, 按左鍵→ 移動滑鼠游標到New 命令, 按左鍵→ 出現如下的視窗, 在Language Tool 之處勾選Enhanced Holtek C compiler/Assembler文件編號版別 1.20日期2008/5/26 第6 頁共189 頁2.2 已開啟專案後, 如何選用Holtek C 編譯器若專案(project) 已開啟之後, 可以點選(click) Option 選單下的Project Setting 命令,在Language Tool 中點選Enhanced Holtek C Compiler/Assembler 以設定使用Holtek C 的Enhance 版編譯器Enhance 版的C compiler 包括ehcc32srsc.exe , ehcc32mrsc.exe 與ehcc32mrmc.exe 三個執行檔此版本必須在HT-IDE3000 V7.0 或以上的系統才能執行第三章微控制器 C 語言程式的速成本章介紹如何快速撰寫微控制器的 C 語言應用程式. 已熟悉ANSI C 標準語言的用法或有撰寫的經驗者, 在閱讀此章後即可開始設計撰寫微控制器的 C 應用程式, 以下各節是基本的C 程式成員, 某些是必須要有的, 如3.1, 其他的則視微控制器的功能及應用來決定是否需要3.1 定義主函式main()#include “ht46r63.h”void main(void){int Flag ;……TurnOn_LCD() ;Flag = LCD_display(cstr) ;TurnOff_LCD() ;……}主函式的返回資料型態(return type)必須是void, 而且不能有參數檔案ht46r63.h 定義與微控制器有關的常數, 例如暫存器的位址定義, 將之引入(include) 可增加程式的可讀性.3.2定義副函式(sub-function)視程式的大小及功能決定是否需要定義副函式. 基本上, 主函式應將應用程式的架構做成模組化, 不需要將所有的程式皆放在主函式中. 為了能很快的完成及了解應用程式, 主函式中只需要包含(呼叫) 定義各功能的副函式即可, 無論在設計或維護程式時皆能很快的進入與完成.例如, 關於LCD 的開啟, 顯示及關閉等功能就可分別定義為單獨的副函式, 如下例. 任何其他的函式或其他的應用專案都可去呼叫這些副函式. 若設計成通用型的, 也可藉由程式館管理器(Library Manager) 將之建入程式館檔案, 以供其他應用專案使用.void TurnOn_LCD(void){}int LCD_display(char *cstr){}void TurnOff_LCD(void){}3.3定義全域變數(global variable)程式在運行中會需要一些變數做為資料存放的地方, 由於微控制器資料記憶體大小的限制及C 編譯器的設計, 最好將常需使用的變數定義為全域型的變數, 在編譯程式的大小與執行上皆較佳. 例如定義常數型指標變數cstr 指到字串“Hello!”, 則可如下const char *cstr = “Hello!” ;3.4定義中斷服務函式(Interrupt Service Routine : ISR) 若微控制器的周邊裝置具有中斷功能,程式也需要此中斷機能以完成工作時, 則必須定義此周邊裝置的中斷服務函式(Interrupt Service Routine, ISR), 如下的格式#pragma vector ISR_tmr0 @ 0x0cvoid ISR_tmr0(void){tick++ ;}中斷服務函式必須遵守下列規定→ 返回的資料型態必須是void→ 不能有參數(必須為void)→ 必須使用前置處理指令#pragma vector 設定中斷向量值(interrupt vector), 在函式名稱(本例子是ISR_tmr0) 之後加上@ 及中斷向量值(本例是0x0c). 也可使用先前定義好的常數, 例如#define VECTOR_TMR0 0x0c#pragma vector ISR_tmr0 @ VECTOR_TMR0void ISR_tmr0(void){}3.5 其他上述的主函式, 副函式及中斷服務函式不需要定義在同一個原始程式檔案內. 為縮短編譯的時間, 最好是分別定義在不同的檔案中, 並使用有意義的檔名, 方便日後找尋所要的函式.第四章 C 程式語言基本上, Holtek C 是仿ANSI (美國國家標準局) 標準的 C 語言, 為配合盛群八位元微控制器的架構, 將提供一些特殊的語法去存取或控制微控制器的資源. 另外, 本章會從八位元微控制器的角度, 說明如何使用 C 語言設計及撰寫微控制器的應用程式4.1 C 程式架構C 語言的程式是由敘述(statements) 所組成, 每個敘述的最後必須有分號‘;’ 做為結束符號.敘述分為四類:→ 宣告(declaration), 宣告變數及資料型態, 資料結構.例如char flag, tick_cnt ; // 宣告變數flag 與tick_cnt 為char 型態→ 定義(definition), 定義變數數值及位址例如int total = 10 ; // 定義變數total, 設定值為10→ 描述式(expression), 執行數學及邏輯運算, 控制程式的流程例如count = ( input > 10) ? 10 : input ;→ 函式呼叫(function), 執行函式的功能例如putchar(ch) ; // 寫出一個字元到輸出口每個敘述可以附加註解做說明. C 編譯器不會對註解做編譯, 下列為兩種可被接受的註解→ 介於符號/* 與符號*/ 之間的數據及文字, 包括換行字‘\n’如果/* 與*/ 不在同一行, 則其間所有的行皆會被視為註解例如/* this is a comment 1 */→ 從符號// 開始到本行的結束皆被視為註解例如// 這是註解的新寫法在 C 語言中, 程式執行區(program block)是以函式的格式定義, 因此, 所有要執行的敘述皆需定義(包含)於某個函式(function) 中, 例如描述式.4.2 開始用C 語言設計一個程式依照下列步驟¸使用 C 語言實作一個簡單的應用程式4.2.1 定義主函式main範例void main(void){}在 C 語言中, 主函式main 是程式執行的起點, 有如組合語言程式中的startORG 00jmp startstart :void 是資料型態, main 與void 皆是保留字, 必須用此字, 小寫字母4.2.2 將標頭檔引入(include a header file)範例#include “ht46r63.h”// 引入標頭檔ht46r63.hvoid main(void){}標頭檔ht46r63.h 中定義許多與微控制器有關的變數及文字符號(symbol). 接下來寫程式時可以使用這些變數與文字符號(symbol), 好處是寫程式或維護程式時會很容易了解程式的功能, 增加程式的易讀性. 例如unsigned char _pa @0x12 ;定義_pa 是一個unsigned char 型態的變數, 它的位址在RAM 的0x12 (就是A埠, port A). 所以程式中如下的敘述_pa = 0 ;則與組合語言的CLR PA ; (PA=[12H]) 有相同的功能4.2.3 定義文字符號及變數在程式中使用文字符號能夠更容易的讀懂程式及修改, 例如定義文字符號_pa0 如下#define _pa0 _12_0表示_pa0 是RAM 位址12H 的位元0 (bit 0), 就是 A 埠的位元0. 下列敘述_pa0 = 1 ;表示將 A 埠的位元0 設為1, 與組合語言程式的SET [12H].0 有相同的功能前置處理指令#define 是定義一個文字符號代表數值, 或是文字串, 或是巨集指令.C 編譯器的前置處理器(preprocessor) 在編譯前, 會先替換這些定義的文字符號.前置處理指令#undef 是將先前定義過的文字符號取消, 變成無效. 詳細的說明請參閱第 4.9 節微控制器中其他暫存器的變數或文字符號, 皆定義於對應之微控制器的標頭檔案內, 在設計程式時可參考之. 可以定義一些程式需要, 但是在標頭檔案中沒有定義的變數或文字符號, 方便程式的開發及維護, 例如#include #define “ht48R50A-1.h”scl _pa3 // SCL (時鐘線) 接到MCU 的A 埠的第3 位元#define scl_c _13_3 // A 埠之控制暫存器的第3 位元(bit 型變數)#define sda _pa1 // SDA (資料線) 接到MCU 的A 埠的第1 位元#define sda_c _13_1 // A 埠之控制暫存器的第1 位元void main(void){}定義四個文字符號scl, scl_c, sda, sda_c 分別代表不同的輸出/輸入埠定義變數會佔用RAM/ROM 的空間, 如果又指定位址, 則此變數佔用此位址, 否則Linker 在做連結時才會分派位址給變數. 其效果有如組合語言的_pa DB ?定義文字符號的效果則與組合語言的EQU 相同, 例如#define scl _pa3 與scl EQU _pa3有相同的效果4.2.4 設定微控制器及裝置的初始狀態根據程式的功能, 設定微控制器中各裝置的初始值, 例如周邊設備的初始狀態, 暫存器的型態等.scl_c = 0 ; // 設定SCL (= PAC) 的狀態為輸出sda_c = 0 ; // 設定SDA (=PA) 的狀態為輸出4.2.5 設計子函式獨立之功能可分別用子函式完成, 在程式的偵錯, 維護及重複使用上皆有好處. 在設計時需要注意函式的參數,返回值等. 通常會將主函式main() 放在程式檔的最後, 各個子函式定義在前面或其他的程式檔案內. 下列範例只是部份, 詳細的說明可參閱4.6 節.#include “ht48r50a-1.h”// 引入標頭檔#define scl _pa3 // SCL (時鐘線) 接到MCU 的A 埠的第 3 位元#define scl_c _13_3 // A 埠(位址0x13)之控制暫存器的第3 位元(bit 型變數) #define sda _pa1 // SDA (資料線) 接到MCU 的A 埠的第1 位元#define sda_c _13_1 // A 埠(位址0x13)之控制暫存器的第1 位元// 函式: StartCondition() 子函式// 功能: 開始一個命令// 輸入: 無// 輸出: 無void StartCondition(void){sda = 1 ; // SDA 輸出highscl = 1 ; // SCL 拉highsda = 0 ; // SDA 輸出lowscl = 0 ; // 完成Start of command}// 函式: StopCondition()// 功能: 結束先前的命令// 輸入: 無// 輸出: 無void StopCondition(void){}// 函式: main()// 功能: 主函式// 輸入: 無// 輸出: 無void main (void){unsigned char Rdata, type ;// 暫存器的初始設定scl_c = sda_c = 0 ; // 將A 埠的位元1, 3 設為輸出型態(SCL, SDA 為輸出)StartCondition() ; // 呼叫子函式……}4.2.6 設計中斷服務函式針對有硬體中斷的微控制器, 需要設計中斷服務函式以處理中斷事件定義周邊裝置的中斷服務函式(Interrupt Service Routine, ISR) 如下格式#pragma vector ISR_tmr0 @ 0x0cvoid ISR_tmr0(void){tick++ ;}中斷服務函式必須遵守下列規定→ 返回的資料型態必須是void→ 不能有參數→ 必須設定中斷向量值(interrupt vector), 在函式名稱(本例子是ISR_tmr0之後加上@ 及中斷向量值(本例是0x0c). 也可使用先前定義好的常數, 例如#define VECTOR_TMR0 0x0c#pragma vector ISR_tmr0 @ VECTOR_TMR0void ISR_tmr0(void){}4.3變數(variable) 及資料型態(data type)程式執行過程中, 可能會需要暫存一些資料, 例如旗標, 執行次數, 延遲秒數等, 因此就必須定義變數以儲存這些資料. 由於變數要佔用程式記憶體(PROM) 或資料記憶體(RAM), 因此在使用變數之前, 定義變數的資料型態, 以便讓編譯器正確的編譯程式及配置記憶體空間.除了資料型態之外, 還可加入儲存類別(storage class) 及修飾詞(qualifier), 對變數做更詳細的安置.4.3.1 變數名變數名的規則→ 第一個字元必須是英文字母或底線符號(underscore), 之後可緊接著字母或數字→ 變數名的前32 個字元有效→ 變數名內不可有+, - , *, / , ……等符號字元→ 英文字母的大小寫是有區別的(case-sensitive), 例如count 與Count 是不同的變數名範例, number, total_tick, _tick 是合法的變數名, 而2num, $dot, line\n 是非法的變數名4.3.2 資料型態* float, double 皆使用IEEE754 32 位元的格式4.3.3 變數的有效範圍(scope)根據變數定義的所在¸決定此變數的有效範圍. 可分為→ 區域變數(local variable)定義在程式區塊內(program block, 例如函式)的變數皆是區域變數. 只有當此程式區塊被執行時, 區域變數才會有效, 而在執行完畢並離開此程式區塊後, 這些區域變數將無效. 程式區塊是指包含在左右大括號‘{‘ 及‘}’ 之間的敘述行定義在函式中的static 變數則是全域變數, 參考 4.3.2 說明→ 全域變數(global variable)定義在所有函式之外的變數為全域變數. 當程式在執行時, 此變數皆有效, 任何函式都可以存取或修改這個變數範例#include “ht48r50a-1.h”unsigned char flag ; // 全域變數void main(void){ char type ; // 區域變數, 只有在此函式被執行時才有效static status = 0 ; // static 變數, 只在第一次執行時設為0……}4.3.4 變數的資料型態(data type)當宣告變數時,必須指定它的資料型態, 以告知編譯器此變數所需記憶體的大小. 資料型態分為整數型(integer type)及浮點數型(floating point type). 整數型又可區分為有正負號(signed) 及無正負號(unsigned).整數型(integer)→ char佔用一個位元組(byte) 的記憶體空間. 如加上signed 則表示有正負號, 其大小範圍是–128 到127. 若加上unsigned, 則表示沒有正負號, 其大小範圍是0到255. 如果沒有signed 或unsigned, 則被視為signed. 可用此型態定義字元,如‘A’, ‘d’, ‘$’, ‘3’等→ short佔用兩個位元組(2 bytes) 的記憶體空間, 如加上signed 則表示有正負號, 其大小範圍是–32768 到32767. 若加上unsigned, 則表示沒有正負號, 其大小範圍是0 到65535. 如果沒有signed 或unsigned, 則被視為signed.Holtek C 採用little-endian 格式, 就是變數的低位元組(least significant byte) 存放在記憶體的低位址. 例如變數count = 0x1234 是存放於記憶體40H 的位址, 則低位元組的數值0x34 存放於位址40H, 高位元數值0x12 存放於位址41H.→ int與short 型態相同→ long佔用四個位元組(4 bytes) 的記憶體空間, 如加上signed 則表示有正負號, 其大小範圍是–2147483648 到2147483647. 若加上unsigned, 則表示沒有正負號, 其大小範圍是0 到4294967295. 如果沒有signed 或unsigned, 則被視為signed在little-endian 格式中, 32位元的變數, 則是先存低字元(least significant word) 的低位元組(least significant byte)到記憶體的低位址, 再存放低字元的高位元組(high byte), 再存放高字元(high word)的低位元組, 最後才是高字元的高位元組浮點型(floating point)Holtek C 支援IEEE 754 32 位元的格式. 包括float 及double 兩個資料型態, 浮點數值是以下表的格式儲存在記憶體與浮點數值的關係式為number = (-1)sign x 2(exponent – 127) x 1.mantissa例如, 浮點數為 2.77000e+37 在儲存到記憶體時換成7DA6B69B 共佔32 位元4.3.5 bit 資料型態類似整數型, 但是只有0 或 1 兩個值, 所以只會取整數的最低位值(LSB:least significant bit) 需要注意下列用法→ bit 型態不可與auto 一起使用, bit 型態的變數不可當函式的參數, 不可用於指標(pointer) 的數據型態, 不可設定靜態初始值(static)→ bit 型態可以設為函式的返回型態, 它是存於累加器(accumulator) 的相對位置→ 程式開始執行時, 不會設定bit 型變數的初始值, 因此程式必須自行設定初始值→ 以下是合法的使用方式static bit init_flag ; // 定義於函式內則被視為區域變數bit toggle_flag ;→ 範例int data = 0x54 ;bit flag ;flag = data ;則flag = 0 (取data 的LSB)如果微控制器具有一個以上的RAM bank, 例如HT46R63, 在定義bit 型態的變數時需要使用前置處理指令#pragma rambank0 指定在RAM bank 0, 如下#pragma rambank0bit flag ;#pragma norambank4.3.6儲存類別(storage class) 與修飾詞(qualifier)變數於宣告或定義時必須指定其資料型態, 但是儲存類別及修飾詞是可選擇的, 可根據應用時的需要去設定或不使用.儲存類別(storage class)儲存類別與區域變數(local variable)及全域變數(global variable)有關.→ 儲存類別autoauto 是給區域變數使用的, 沒有指定儲存類別的區域變數皆是auto寫與不寫auto 都是相同效力. 區域變數是存放在RAM bank 0 的空間→ 儲存類別registerregister 與auto 類似, 是給區域變數用的, 當變數的存取很頻繁時, 可將之設為register, C 編譯器會使用暫存器而非資料記憶體空間來存放此變數, 如此可增加存取的速度及減少編碼. 目前並未實做此功能.→ 儲存類別staticstatic 的變數會一直有效到整個程式結束後才失效. 它的初始值只會在程式開始執行時被設定一次. 雖然static 的變數在程式結束前皆有效, 但是定義在函式內的static 變數仍然是區域變數, 必須要在它所定義的函式中才可以讀寫→ 儲存類別externextern 通知C 編譯器此變數是定義在其他的程式檔內, 需要經由連結器(Linker)連結定義此變數的檔案後, 才知道變數的所在.以目前在微控制器的應用程式上, 比較需要使用extern, 其他三種不具特別的優勢可用定義全域變數(global variabl)的方式即可達到相同效果. 建議不要使用.修飾詞(qualifier)→ 修飾詞constC 編譯器會將const 的變數放置於程式記憶體(PROM). 在定義const 變數時, 必須要設定其值, 而程式在執行中不能修改此變數的值→ 修飾詞constant這個修飾詞是Holtek C 編譯器特別提供的. 它會將constant 的變數放置於程式記憶體(PROM) 的最後一頁(last page). 定義constant 變數時,必須要設定其值, 而程式在執行中不能修改此變數的值. 使用此修飾詞要注意下列三點●只能使用在int 或unsigned int 的資料型態●設定值必須配合微控制器程式記憶體的寬度, 例如, 若使用在 HT48R50A-1 時,因為此微控制器的寬度為 15 個位元, 最高位元是無效的, 所以 0x9A 會被 C編譯器改成 0x1A. 最高位元, 位元 15 被清除為 0● 所有設定此修飾詞的變數或陣列, 總共佔用的字位元組 (word) 不可超過 256 個指定詞(specifier)→ 指定詞typedeftypedef 是針對資料型態做新名稱的宣告, 不是宣告資料型態的新變數, 而是宣告一個新的名字. 例如將UCHAR (新名字) 宣告為unsigned char 的資料型態, 可使用typedef unsigned char UCHAR ; // UCHAR 為unsigned char 的新名字UCHAR count ; // 變數count 的資料型態為unsigned char// 等同於unsigned char count ;使用typedef 宣告資料型態的新名字可以讓程式的可讀性更高, 更易了解. 例如,typedef unsigned int WORD ; // 使用WORD 代表unsigned int, 16 bitstypedef unsigned long DWORD ; // DWORD 代表32 bit 的double word4.3.7絕對變數(absolute variable)可以將全域變數或static 變數指定一個固定的記憶體的位址, 例如unsigned char PortA @ 0x12 ;在變數名的後面再加上‘@’及位址C 編譯器在編譯時會將程式中出現絕對變數的程式改為此位址, 但並未在記憶體中保留位置給此變數, 所以從連結器(Linker) 產出的對映檔(map file)中找不到此變數 C 編譯器會將之翻成組合語言的EQU 指令,如下_PortA EQU 12h此種用法主要是對微控制器內的暫存器做定義, 方便閱讀程式4.3.8常數(constant)整數型常數(integral constant) 可使用基底(radix)格式表示之.若常數的最後一字為l 或L, 則表示它使用signed long 或unsigned long 的型態. 字尾是u 或U, 則表示常數為unsigned 型態.浮點型(floating point)常數的型態是double, 若它的字尾是 f 或F, 則是float.字元常數(character constant)必須以單引號‘ ‘ 框住, 例如‘a’字串常數(string constant) 必須以雙引號“ “ 框起, 例如“Hello!”. 字串常數的定義會影響它所儲存的記憶體位址, 如下char *cp = “one” ; // C 編譯器會發出錯誤const char *sptr = “Hello” ; // “Hello” 儲存在程式記憶體(PROM) 常數型的變數或陣列(array)必須要設定其值, 否則C 編譯器會發出錯誤訊息,如上例4.3.9指標(pointer) 與陣列(array)指標本身是一個變數, 它的內容是另一個變數存放的位址, 類似組合語言的間接定址.在使用上, 指標必須要指到一個已定義(存放於記憶體) 的變數, 否則在程式執行時會發生錯誤. 指標的宣告格式資料型態*指標名[, *指標名,….] ; 資料型態是這個指標所指的變數的資料型態, 例如char. 指標名類似變數名, 可以在一行中, 宣告指向相同資料型態的不同指標名, 例如char *tptr, *array_ptr ;int *line_ptr ;以上只是宣告指標變數, 必須要將這些指標指向已定義的變數才能使用指標的運算子& 與*運算子& 如果緊鄰在變數的前面, 例如&line, 則是代表取得此變數的記憶體位址例如,int line ; // 定義變數int *line_ptr ; // 宣告指標line = 12 ;line_ptr = &line ;若變數line 被安置於RAM 的位址64, 則指標line_ptr 等於64運算子* 緊鄰指標變數之前是表示取得這個指標指到的變數的內容, 承上例, int total ; // 定義變數total = *line_ptr ; // 取得指標line_ptr 所指到的變數line 的內容則變數total 等於12指標的大小會根據微控制器具有之記憶體空間大小而定, 如果微控制器具有一個以上的RAM bank, 則指標本身會使用兩個位元組來儲存被指到的變數的位址如果變數有const 或constant 修飾詞, 則是指向程式記憶體(PROM), 而且此變數的內容不能被修改. 如果所指向的變數不具有const 或constant, 則指標會指向資料記憶體(data memory, RAM) 內的變數.陣列(array)陣列是由相同資料型態的元素組成的, 例如char array_name[32] ;是由32 個char 型態的元素組成的, 這些元素的名字是以陣列名array_name 為準, 而以索引(index) 區分各個元素, 例如array_name[3] 是第 4 個元素. 陣列的索引是正整數, 從0 開始直到元素的總個數減一, 上例中, 最後一個元素是array_name[31]. 這種資料型態在建表格(table) 時非常有用陣列也可當做指標的一種, 只是使用時格式不同, 下列範例說明指標與陣列之間的使用方法char *nptr, *fptr ; // 宣告指標char ch, tbl ; // 定義變數char table[5] = { ‘a’, ‘b’, ‘c’, ‘d’, ‘e’ } ; // 定義陣列nptr = table ; // 指標nptr 指到陣列table 的第一個元素table[0]ch = *nptr ; // 將字元‘a’ 存入變數chtbl = table[0] ; // 將字元‘a’ 存入變數tbl , 所以變數ch 與變數tbl 的內容相同fptr = &table[4] ; // 指標fptr 指到陣列table 的第5 個元素, table[4]ch = *fptr ; // 將字元‘e’ (第5 個元素) 存入變數ch 內tbl = *(nptr+4) ; // nptr 指到陣列table 的第一個元素, 加4, 所以tbl = ‘e’4.3.10結構(struct) 與等位(union)結構是一個或多個成員的集合, 每個成員的資料型態可以不同, 並且使用結構的名字去讀寫這些成員. 結構的宣告是等同於定義一個新的資料型態, 當變數宣告為一個結構的型態時, 便可用結構的名字去讀寫各成員的內容.成員的資料型態不可以使用bit 型態, 但是可以用bit-field 方式宣告成員的型態, 例如struct str_name {unsigned flag : 1 ; // 此成員放於最低位元least significant bitunsigned no_used : 7 ;unsigned stack : 5 ; // 此成員置於最高位元high bits} usage ;每個bit field 會置放於16 位元的單位內, 不會橫跨兩個16位元的單位等位(union) 的格式與結構相同, 唯一不同的是記憶體空間的分配方式. 等位是安排共用的空間來存放不同資料型態的成員. 每個成員必須要宣告其資料型態, 而等位的大小則是所有成員中佔用最大位元組(bytes)的型態大小. 每個成員的開始位址皆相同, 就是等位的位址.union union_name {char num_byte ; // 佔用1 個位元組。
HOLTEK C语言学习教程
void main()
//程序从这里开始跑
{
_nop();
//语句 1
_nop();
//语句 2
_nop();
//语句 3
}
功能说明:程序执行的顺序,语句 1—>语句 2—>语句 3。
(2) 子函数
一个程序包含各种功能,如果每种功能都做成一个子函数,那么整个程序的架
构实现了模块化。
例如,LCD 的开启,显示及关闭这三个功能可以分别做成三个独立的子函数。
第一课时
1、 Holtek 公司编译器 HT-IDE3000 使用说明 (1) 双击打开 HT-IDE3000,进入编译器的界面,见下图:
(2) 单击“工程”——>选择“新建”,弹出下图窗口;
——Project Name:新建项目文件的名称,不建议使用中文名称; ——Project Location:项目文件存放的位置,勾选“Create directory for project”后,会
4 变量命名规则
——第一个字符必须是英文字母或底线符号”_”,之后可紧接字母或数字。
——变量名不能超过 32 个字符。
——英文字母的大小写是有区别的。
例如:count,count2,_count,_count2
5 变量的有效范围
——定义在函数里面,变量有效范围在此函数范围内。
——定义在函数外面,变量有效范围是整个程序。
#include "HT66F40.h"
#define u8 unsigned char u8 a,b,c; u8 max(u8 x,u8 y);
//程序中 u8 与 unsigned char 等价 //声明变量 a,b,c //声明函数 max,函数功能为比较两个数大小
合泰单片机串口通讯C语言
合泰单片机串口通讯C语言/*和泰单片机串口通许,已调试通过,抗干扰超强,一些标志及定时器请自己定义*/ unsigned char count_uartout;//发送计数器unsigned cha datin_buf[4]; //接收寄存器4个unsigned cha datout_buf[9]; //发寄存器9个#define tongxun_in datin_buf[0] //接收送识辨码寄存器#define tongxun_out datout_buf[0] //发送识辨码寄存器#define send_max 8 //设发的数据个数DEFINE_ISR (Interrupt_uart, 0x2c) //串口中断地址{if(++count_uartin>3)count_uartin=0;if((_usr&0b11110000)==0) //判断是否出错{if(_rx8) //接收到首数据{tongxun_in=_txr_rxr;if(tongxun_in==0x5a) 首数据正常则{b_sendero=0; //清除错误标志count_uartin=0; //接收数据地址清零tongxun_time=0; //通许计时器清0,tongxun_time为1S计时器,到1S则b_tongxun=1;表示接收错误。
b_tongxun=0;}else b_sendero=1; //接收的数据出错}else //出错处理{if(!b_sendero)datin_buf[count_uartin]=_txr_rxr; //接收的数据正常else b_tongxun=_txr_rxr; //接收的数据出错,需读_txr_rxr清除_usr的错误标志}}elseb_tongxun=_txr_rxr;// //接收的数据出错,需读_txr_rxr清除_usr 的错误标志}//---------------------------------------------------void send_out( ) //P_cs p_clk p_din p_dout zhu {if(_txif){if(++count_uartout>send_max){count_uartout=0;_tx8=1;}else _tx8=0;_txr_rxr=datout_buf[count_uartout];}}pro_100ms(){ if(b_1000ms){b_100ms=0;if(++tongxun_time>15) b_tongxun=1;}}void main(){datout_buf=0x5a;_ucr1=0b11001001;_ucr2=0b11101100;_emi = 1; //开总中断_brg=6;//开串口中断_uarte=1;////开串口中断while(1){send_out( );}}。
合泰C语言用户手册
字符型常量 ..........................................................................................6
字符串常量 ..........................................................................................6
指针与数组 ................................................................................................17
指针 ....................................................................................................17
保留字 ..................................................................................................3
数据类型 ......................................................................................................3
枚举常量 ..............................................................................................6
运算符..........................................................................................................7
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Holtek 微控制器應用範例–使用Holtek C 語言目錄第一章內容簡介第二章選定Holtek C 語言的使用環境2.1 進入HT-IDE3000 建立新的專案時, 選定Holtek C 編譯器2.2 已開啟專案後, 選用Holtek C 編譯器第三章微控制器C 語言程式的速成3.1 定義主函式main()3.2定義副函式(sub-function)3.3定義全域變數(global variable)3.4定義中斷服務函式(Interrupt Service Routine : ISR)3.5 其他第四章 C 語言程式4.1 C 程式架構4.2 開始用C 語言設計一個程式4.2.1 定義主函式main4.2.2 將標頭檔引入(include a header file)4.2.3 定義文字符號及變數4.2.4 設定微控制器及裝置的初始狀態4.2.5 設計子函式4.2.6 設計中斷服務函式4.3變數(variable) 及資料型態(data type)4.3.1 變數名4.3.2 資料型態4.3.3 變數的有效範圍(scope)4.3.4 變數的資料型態(data type)整數型(integer)浮點型(floating point)4.3.5 bit 資料型態4.3.6儲存類別(storage class) 與修飾詞(qualifier)儲存類別(storage class)修飾詞(qualifier)4.3.7絕對變數(absolute variable)4.3.8常數(constant)4.3.9指標(pointer) 與陣列(array)指標的運算子& 與*陣列(array)4.3.10結構(struct) 與等位(union)結構的運算子-> 與.4.4運算子(Operators)運算前的型態轉換4.5程式流程控制(program flow control)4.5.1if-else 敘述4.5.2switch 敘述4.5.3for 敘述4.5.4while 敘述4.5.5do-while 敘述4.5.6goto 敘述4.5.7break 與continue 敘述4.6函式(Functions)4.6.1參數(arguments)4.6.2返回值(return values)4.7中斷服務函式(Interrupt Service Routines)4.8在C 語言程式中嵌入組合語言(in-line assembly code)從組合語言的程式去存取 C 語言的物件(變數)4.9前置處理指令(Preprocessor)4.9.1 定義文字符號(#define)4.9.2引入檔案(#include)4.9.3內嵌組合語言(inline assembly)4.9.4 條件式編譯(#if/#endif)4.9.5 編譯器的特殊選項pragma4.10Holtek C 編譯器的內建函式(built-in functions)第五章基本 C 語言程式5.1 語法觀念5.2 迴圈的應用(loop)5.3 撰寫MCU 應用程式的注意事項5.4 可供微控制器應用程式使用的範本5.5 設計微控制器應用程式的小技巧第六章程式範例–初級6.1LED 跑馬燈6.2LED 霹靂燈6.3 單顆七段顯示器6.4 5*5 點矩陣LED 顯示6.5 HT48 微控制器控制HT1621 LCD 的顯示6.6 HT48 微控制器控制LCD 模組的顯示6.7 具LCD 驅動功能的微控制器之顯示應用程式– HT46R636.8 顯示器的通用函式– HT44780 LCM6.9 鍵盤掃描程式第七章程式範例–中斷函式7.1 用時鐘控制LED 的亮與滅7.2 類比/數位轉換(ADC) 的應用第八章HT46R52A 應用於鎳氫電池充電器(HA0084T)第九章程式範例– HT46R74D-1 胎壓計(HA0105T)第一章內容簡介盛群半導體公司(Holtek)開發一系列的八位元微控制器(micro-controller, MCU). 當開發微控制器的應用程式時, 除了可使用盛群提供的組合語言(assembly language),也可使用標準的C 語言編譯器(C compiler).由於八位元微控制器的記憶體空間, 不論是程式記憶體(program memory space)或是資料記憶體(ram memory space), 皆是有限制的, 通常會使用組合語言開發應用程式. 但是越來越多的微控制器支援更多的記憶體以及更多的功能, 使得程式也相對的擴大. 如果仍然使用組合語言開發程式, 不但費時費力, 未來在維護及擴增功能的工作上也相當困難.因此, 使用高階程式語言, 例如C 語言, 來開發應用程式就是一種可行的趨勢.C 語言是高階程式語言中的一種, 它具有高度的的可讀性及可移植性(portability),除了能夠快速地完成應用程式的開發與偵錯, 也很容易移植到其他的微控制器上. 當程式需要縮減或擴充功能時, 也很容易的完成, 因此很適合於微控制器的程式開發.本書主要是以Holtek C 語言為主, 說明如何使用Holtek C 語言撰寫盛群微控制器的應用程式, 包括 C 的程式架構, C 語言的一般用法, 特殊用法及應用範例書中將說明在開發微控制器的應用程式時需要注意的地方及如何撰寫會比較恰當, 並配以實例解釋.讀者可以參考修改或直接採用到自己的程式中, 再用發展工具HT-ICE, HT-IDE3000 驗證之.第二章介紹選用Holtek C 編譯器的步驟, 指引HT-IDE3000 呼叫Holtek C 編譯器去編譯C 語言的原始程式.第三章提供一種快速撰寫 C 程式的方法, 對ANSI C 語言熟悉的用者, 可於閱讀本章之後即開始撰寫微控制器的 C 語言程式第四章介紹C 語言, 未曾使用過 C 語言的讀者應仔細閱讀本章以了解 C 語言的用法第五章介紹使用 C 語言寫程式的基本觀念, 注意事項及建議的寫作方法第六章到第九章則是應用範例, 針對盛群各系列的微控制器, 以 C 語言撰寫的應用程式. 包含有功能說明, 應用電路及程式說明.文件編號版別 1.20日期2008/5/26 第5 頁共189 頁第二章選定Holtek C 編譯器的使用環境2.1 進入HT-IDE3000, 建立新的專案時, 選定Holtek C 編譯器進入HT-IDE3000 開發環境後, 依照下列方法建立一個新的專案(project)→ 移動滑鼠游標到Project 選單, 按左鍵→ 移動滑鼠游標到New 命令, 按左鍵→ 出現如下的視窗, 在Language Tool 之處勾選Enhanced Holtek C compiler/Assembler文件編號版別 1.20日期2008/5/26 第6 頁共189 頁2.2 已開啟專案後, 如何選用Holtek C 編譯器若專案(project) 已開啟之後, 可以點選(click) Option 選單下的Project Setting 命令,在Language Tool 中點選Enhanced Holtek C Compiler/Assembler 以設定使用Holtek C 的Enhance 版編譯器Enhance 版的C compiler 包括ehcc32srsc.exe , ehcc32mrsc.exe 與ehcc32mrmc.exe 三個執行檔此版本必須在HT-IDE3000 V7.0 或以上的系統才能執行第三章微控制器 C 語言程式的速成本章介紹如何快速撰寫微控制器的 C 語言應用程式. 已熟悉ANSI C 標準語言的用法或有撰寫的經驗者, 在閱讀此章後即可開始設計撰寫微控制器的 C 應用程式, 以下各節是基本的C 程式成員, 某些是必須要有的, 如3.1, 其他的則視微控制器的功能及應用來決定是否需要3.1 定義主函式main()#include “ht46r63.h”void main(void){int Flag ;……TurnOn_LCD() ;Flag = LCD_display(cstr) ;TurnOff_LCD() ;……}主函式的返回資料型態(return type)必須是void, 而且不能有參數檔案ht46r63.h 定義與微控制器有關的常數, 例如暫存器的位址定義, 將之引入(include) 可增加程式的可讀性.3.2定義副函式(sub-function)視程式的大小及功能決定是否需要定義副函式. 基本上, 主函式應將應用程式的架構做成模組化, 不需要將所有的程式皆放在主函式中. 為了能很快的完成及了解應用程式, 主函式中只需要包含(呼叫) 定義各功能的副函式即可, 無論在設計或維護程式時皆能很快的進入與完成.例如, 關於LCD 的開啟, 顯示及關閉等功能就可分別定義為單獨的副函式, 如下例. 任何其他的函式或其他的應用專案都可去呼叫這些副函式. 若設計成通用型的, 也可藉由程式館管理器(Library Manager) 將之建入程式館檔案, 以供其他應用專案使用.void TurnOn_LCD(void){}int LCD_display(char *cstr){}void TurnOff_LCD(void){}3.3定義全域變數(global variable)程式在運行中會需要一些變數做為資料存放的地方, 由於微控制器資料記憶體大小的限制及C 編譯器的設計, 最好將常需使用的變數定義為全域型的變數, 在編譯程式的大小與執行上皆較佳. 例如定義常數型指標變數cstr 指到字串“Hello!”, 則可如下const char *cstr = “Hello!” ;3.4定義中斷服務函式(Interrupt Service Routine : ISR) 若微控制器的周邊裝置具有中斷功能,程式也需要此中斷機能以完成工作時, 則必須定義此周邊裝置的中斷服務函式(Interrupt Service Routine, ISR), 如下的格式#pragma vector ISR_tmr0 @ 0x0cvoid ISR_tmr0(void){tick++ ;}中斷服務函式必須遵守下列規定→ 返回的資料型態必須是void→ 不能有參數(必須為void)→ 必須使用前置處理指令#pragma vector 設定中斷向量值(interrupt vector), 在函式名稱(本例子是ISR_tmr0) 之後加上@ 及中斷向量值(本例是0x0c). 也可使用先前定義好的常數, 例如#define VECTOR_TMR0 0x0c#pragma vector ISR_tmr0 @ VECTOR_TMR0void ISR_tmr0(void){}3.5 其他上述的主函式, 副函式及中斷服務函式不需要定義在同一個原始程式檔案內. 為縮短編譯的時間, 最好是分別定義在不同的檔案中, 並使用有意義的檔名, 方便日後找尋所要的函式.第四章 C 程式語言基本上, Holtek C 是仿ANSI (美國國家標準局) 標準的 C 語言, 為配合盛群八位元微控制器的架構, 將提供一些特殊的語法去存取或控制微控制器的資源. 另外, 本章會從八位元微控制器的角度, 說明如何使用 C 語言設計及撰寫微控制器的應用程式4.1 C 程式架構C 語言的程式是由敘述(statements) 所組成, 每個敘述的最後必須有分號‘;’ 做為結束符號.敘述分為四類:→ 宣告(declaration), 宣告變數及資料型態, 資料結構.例如char flag, tick_cnt ; // 宣告變數flag 與tick_cnt 為char 型態→ 定義(definition), 定義變數數值及位址例如int total = 10 ; // 定義變數total, 設定值為10→ 描述式(expression), 執行數學及邏輯運算, 控制程式的流程例如count = ( input > 10) ? 10 : input ;→ 函式呼叫(function), 執行函式的功能例如putchar(ch) ; // 寫出一個字元到輸出口每個敘述可以附加註解做說明. C 編譯器不會對註解做編譯, 下列為兩種可被接受的註解→ 介於符號/* 與符號*/ 之間的數據及文字, 包括換行字‘\n’如果/* 與*/ 不在同一行, 則其間所有的行皆會被視為註解例如/* this is a comment 1 */→ 從符號// 開始到本行的結束皆被視為註解例如// 這是註解的新寫法在 C 語言中, 程式執行區(program block)是以函式的格式定義, 因此, 所有要執行的敘述皆需定義(包含)於某個函式(function) 中, 例如描述式.4.2 開始用C 語言設計一個程式依照下列步驟¸使用 C 語言實作一個簡單的應用程式4.2.1 定義主函式main範例void main(void){}在 C 語言中, 主函式main 是程式執行的起點, 有如組合語言程式中的startORG 00jmp startstart :void 是資料型態, main 與void 皆是保留字, 必須用此字, 小寫字母4.2.2 將標頭檔引入(include a header file)範例#include “ht46r63.h”// 引入標頭檔ht46r63.hvoid main(void){}標頭檔ht46r63.h 中定義許多與微控制器有關的變數及文字符號(symbol). 接下來寫程式時可以使用這些變數與文字符號(symbol), 好處是寫程式或維護程式時會很容易了解程式的功能, 增加程式的易讀性. 例如unsigned char _pa @0x12 ;定義_pa 是一個unsigned char 型態的變數, 它的位址在RAM 的0x12 (就是A埠, port A). 所以程式中如下的敘述_pa = 0 ;則與組合語言的CLR PA ; (PA=[12H]) 有相同的功能4.2.3 定義文字符號及變數在程式中使用文字符號能夠更容易的讀懂程式及修改, 例如定義文字符號_pa0 如下#define _pa0 _12_0表示_pa0 是RAM 位址12H 的位元0 (bit 0), 就是 A 埠的位元0. 下列敘述_pa0 = 1 ;表示將 A 埠的位元0 設為1, 與組合語言程式的SET [12H].0 有相同的功能前置處理指令#define 是定義一個文字符號代表數值, 或是文字串, 或是巨集指令.C 編譯器的前置處理器(preprocessor) 在編譯前, 會先替換這些定義的文字符號.前置處理指令#undef 是將先前定義過的文字符號取消, 變成無效. 詳細的說明請參閱第 4.9 節微控制器中其他暫存器的變數或文字符號, 皆定義於對應之微控制器的標頭檔案內, 在設計程式時可參考之. 可以定義一些程式需要, 但是在標頭檔案中沒有定義的變數或文字符號, 方便程式的開發及維護, 例如#include #define “ht48R50A-1.h”scl _pa3 // SCL (時鐘線) 接到MCU 的A 埠的第3 位元#define scl_c _13_3 // A 埠之控制暫存器的第3 位元(bit 型變數)#define sda _pa1 // SDA (資料線) 接到MCU 的A 埠的第1 位元#define sda_c _13_1 // A 埠之控制暫存器的第1 位元void main(void){}定義四個文字符號scl, scl_c, sda, sda_c 分別代表不同的輸出/輸入埠定義變數會佔用RAM/ROM 的空間, 如果又指定位址, 則此變數佔用此位址, 否則Linker 在做連結時才會分派位址給變數. 其效果有如組合語言的_pa DB ?定義文字符號的效果則與組合語言的EQU 相同, 例如#define scl _pa3 與scl EQU _pa3有相同的效果4.2.4 設定微控制器及裝置的初始狀態根據程式的功能, 設定微控制器中各裝置的初始值, 例如周邊設備的初始狀態, 暫存器的型態等.scl_c = 0 ; // 設定SCL (= PAC) 的狀態為輸出sda_c = 0 ; // 設定SDA (=PA) 的狀態為輸出4.2.5 設計子函式獨立之功能可分別用子函式完成, 在程式的偵錯, 維護及重複使用上皆有好處. 在設計時需要注意函式的參數,返回值等. 通常會將主函式main() 放在程式檔的最後, 各個子函式定義在前面或其他的程式檔案內. 下列範例只是部份, 詳細的說明可參閱4.6 節.#include “ht48r50a-1.h”// 引入標頭檔#define scl _pa3 // SCL (時鐘線) 接到MCU 的A 埠的第 3 位元#define scl_c _13_3 // A 埠(位址0x13)之控制暫存器的第3 位元(bit 型變數) #define sda _pa1 // SDA (資料線) 接到MCU 的A 埠的第1 位元#define sda_c _13_1 // A 埠(位址0x13)之控制暫存器的第1 位元// 函式: StartCondition() 子函式// 功能: 開始一個命令// 輸入: 無// 輸出: 無void StartCondition(void){sda = 1 ; // SDA 輸出highscl = 1 ; // SCL 拉highsda = 0 ; // SDA 輸出lowscl = 0 ; // 完成Start of command}// 函式: StopCondition()// 功能: 結束先前的命令// 輸入: 無// 輸出: 無void StopCondition(void){}// 函式: main()// 功能: 主函式// 輸入: 無// 輸出: 無void main (void){unsigned char Rdata, type ;// 暫存器的初始設定scl_c = sda_c = 0 ; // 將A 埠的位元1, 3 設為輸出型態(SCL, SDA 為輸出)StartCondition() ; // 呼叫子函式……}4.2.6 設計中斷服務函式針對有硬體中斷的微控制器, 需要設計中斷服務函式以處理中斷事件定義周邊裝置的中斷服務函式(Interrupt Service Routine, ISR) 如下格式#pragma vector ISR_tmr0 @ 0x0cvoid ISR_tmr0(void){tick++ ;}中斷服務函式必須遵守下列規定→ 返回的資料型態必須是void→ 不能有參數→ 必須設定中斷向量值(interrupt vector), 在函式名稱(本例子是ISR_tmr0之後加上@ 及中斷向量值(本例是0x0c). 也可使用先前定義好的常數, 例如#define VECTOR_TMR0 0x0c#pragma vector ISR_tmr0 @ VECTOR_TMR0void ISR_tmr0(void){}4.3變數(variable) 及資料型態(data type)程式執行過程中, 可能會需要暫存一些資料, 例如旗標, 執行次數, 延遲秒數等, 因此就必須定義變數以儲存這些資料. 由於變數要佔用程式記憶體(PROM) 或資料記憶體(RAM), 因此在使用變數之前, 定義變數的資料型態, 以便讓編譯器正確的編譯程式及配置記憶體空間.除了資料型態之外, 還可加入儲存類別(storage class) 及修飾詞(qualifier), 對變數做更詳細的安置.4.3.1 變數名變數名的規則→ 第一個字元必須是英文字母或底線符號(underscore), 之後可緊接著字母或數字→ 變數名的前32 個字元有效→ 變數名內不可有+, - , *, / , ……等符號字元→ 英文字母的大小寫是有區別的(case-sensitive), 例如count 與Count 是不同的變數名範例, number, total_tick, _tick 是合法的變數名, 而2num, $dot, line\n 是非法的變數名4.3.2 資料型態* float, double 皆使用IEEE754 32 位元的格式4.3.3 變數的有效範圍(scope)根據變數定義的所在¸決定此變數的有效範圍. 可分為→ 區域變數(local variable)定義在程式區塊內(program block, 例如函式)的變數皆是區域變數. 只有當此程式區塊被執行時, 區域變數才會有效, 而在執行完畢並離開此程式區塊後, 這些區域變數將無效. 程式區塊是指包含在左右大括號‘{‘ 及‘}’ 之間的敘述行定義在函式中的static 變數則是全域變數, 參考 4.3.2 說明→ 全域變數(global variable)定義在所有函式之外的變數為全域變數. 當程式在執行時, 此變數皆有效, 任何函式都可以存取或修改這個變數範例#include “ht48r50a-1.h”unsigned char flag ; // 全域變數void main(void){ char type ; // 區域變數, 只有在此函式被執行時才有效static status = 0 ; // static 變數, 只在第一次執行時設為0……}4.3.4 變數的資料型態(data type)當宣告變數時,必須指定它的資料型態, 以告知編譯器此變數所需記憶體的大小. 資料型態分為整數型(integer type)及浮點數型(floating point type). 整數型又可區分為有正負號(signed) 及無正負號(unsigned).整數型(integer)→ char佔用一個位元組(byte) 的記憶體空間. 如加上signed 則表示有正負號, 其大小範圍是–128 到127. 若加上unsigned, 則表示沒有正負號, 其大小範圍是0到255. 如果沒有signed 或unsigned, 則被視為signed. 可用此型態定義字元,如‘A’, ‘d’, ‘$’, ‘3’等→ short佔用兩個位元組(2 bytes) 的記憶體空間, 如加上signed 則表示有正負號, 其大小範圍是–32768 到32767. 若加上unsigned, 則表示沒有正負號, 其大小範圍是0 到65535. 如果沒有signed 或unsigned, 則被視為signed.Holtek C 採用little-endian 格式, 就是變數的低位元組(least significant byte) 存放在記憶體的低位址. 例如變數count = 0x1234 是存放於記憶體40H 的位址, 則低位元組的數值0x34 存放於位址40H, 高位元數值0x12 存放於位址41H.→ int與short 型態相同→ long佔用四個位元組(4 bytes) 的記憶體空間, 如加上signed 則表示有正負號, 其大小範圍是–2147483648 到2147483647. 若加上unsigned, 則表示沒有正負號, 其大小範圍是0 到4294967295. 如果沒有signed 或unsigned, 則被視為signed在little-endian 格式中, 32位元的變數, 則是先存低字元(least significant word) 的低位元組(least significant byte)到記憶體的低位址, 再存放低字元的高位元組(high byte), 再存放高字元(high word)的低位元組, 最後才是高字元的高位元組浮點型(floating point)Holtek C 支援IEEE 754 32 位元的格式. 包括float 及double 兩個資料型態, 浮點數值是以下表的格式儲存在記憶體與浮點數值的關係式為number = (-1)sign x 2(exponent – 127) x 1.mantissa例如, 浮點數為 2.77000e+37 在儲存到記憶體時換成7DA6B69B 共佔32 位元4.3.5 bit 資料型態類似整數型, 但是只有0 或 1 兩個值, 所以只會取整數的最低位值(LSB:least significant bit) 需要注意下列用法→ bit 型態不可與auto 一起使用, bit 型態的變數不可當函式的參數, 不可用於指標(pointer) 的數據型態, 不可設定靜態初始值(static)→ bit 型態可以設為函式的返回型態, 它是存於累加器(accumulator) 的相對位置→ 程式開始執行時, 不會設定bit 型變數的初始值, 因此程式必須自行設定初始值→ 以下是合法的使用方式static bit init_flag ; // 定義於函式內則被視為區域變數bit toggle_flag ;→ 範例int data = 0x54 ;bit flag ;flag = data ;則flag = 0 (取data 的LSB)如果微控制器具有一個以上的RAM bank, 例如HT46R63, 在定義bit 型態的變數時需要使用前置處理指令#pragma rambank0 指定在RAM bank 0, 如下#pragma rambank0bit flag ;#pragma norambank4.3.6儲存類別(storage class) 與修飾詞(qualifier)變數於宣告或定義時必須指定其資料型態, 但是儲存類別及修飾詞是可選擇的, 可根據應用時的需要去設定或不使用.儲存類別(storage class)儲存類別與區域變數(local variable)及全域變數(global variable)有關.→ 儲存類別autoauto 是給區域變數使用的, 沒有指定儲存類別的區域變數皆是auto寫與不寫auto 都是相同效力. 區域變數是存放在RAM bank 0 的空間→ 儲存類別registerregister 與auto 類似, 是給區域變數用的, 當變數的存取很頻繁時, 可將之設為register, C 編譯器會使用暫存器而非資料記憶體空間來存放此變數, 如此可增加存取的速度及減少編碼. 目前並未實做此功能.→ 儲存類別staticstatic 的變數會一直有效到整個程式結束後才失效. 它的初始值只會在程式開始執行時被設定一次. 雖然static 的變數在程式結束前皆有效, 但是定義在函式內的static 變數仍然是區域變數, 必須要在它所定義的函式中才可以讀寫→ 儲存類別externextern 通知C 編譯器此變數是定義在其他的程式檔內, 需要經由連結器(Linker)連結定義此變數的檔案後, 才知道變數的所在.以目前在微控制器的應用程式上, 比較需要使用extern, 其他三種不具特別的優勢可用定義全域變數(global variabl)的方式即可達到相同效果. 建議不要使用.修飾詞(qualifier)→ 修飾詞constC 編譯器會將const 的變數放置於程式記憶體(PROM). 在定義const 變數時, 必須要設定其值, 而程式在執行中不能修改此變數的值→ 修飾詞constant這個修飾詞是Holtek C 編譯器特別提供的. 它會將constant 的變數放置於程式記憶體(PROM) 的最後一頁(last page). 定義constant 變數時,必須要設定其值, 而程式在執行中不能修改此變數的值. 使用此修飾詞要注意下列三點●只能使用在int 或unsigned int 的資料型態●設定值必須配合微控制器程式記憶體的寬度, 例如, 若使用在 HT48R50A-1 時,因為此微控制器的寬度為 15 個位元, 最高位元是無效的, 所以 0x9A 會被 C編譯器改成 0x1A. 最高位元, 位元 15 被清除為 0● 所有設定此修飾詞的變數或陣列, 總共佔用的字位元組 (word) 不可超過 256 個指定詞(specifier)→ 指定詞typedeftypedef 是針對資料型態做新名稱的宣告, 不是宣告資料型態的新變數, 而是宣告一個新的名字. 例如將UCHAR (新名字) 宣告為unsigned char 的資料型態, 可使用typedef unsigned char UCHAR ; // UCHAR 為unsigned char 的新名字UCHAR count ; // 變數count 的資料型態為unsigned char// 等同於unsigned char count ;使用typedef 宣告資料型態的新名字可以讓程式的可讀性更高, 更易了解. 例如,typedef unsigned int WORD ; // 使用WORD 代表unsigned int, 16 bitstypedef unsigned long DWORD ; // DWORD 代表32 bit 的double word4.3.7絕對變數(absolute variable)可以將全域變數或static 變數指定一個固定的記憶體的位址, 例如unsigned char PortA @ 0x12 ;在變數名的後面再加上‘@’及位址C 編譯器在編譯時會將程式中出現絕對變數的程式改為此位址, 但並未在記憶體中保留位置給此變數, 所以從連結器(Linker) 產出的對映檔(map file)中找不到此變數 C 編譯器會將之翻成組合語言的EQU 指令,如下_PortA EQU 12h此種用法主要是對微控制器內的暫存器做定義, 方便閱讀程式4.3.8常數(constant)整數型常數(integral constant) 可使用基底(radix)格式表示之.若常數的最後一字為l 或L, 則表示它使用signed long 或unsigned long 的型態. 字尾是u 或U, 則表示常數為unsigned 型態.浮點型(floating point)常數的型態是double, 若它的字尾是 f 或F, 則是float.字元常數(character constant)必須以單引號‘ ‘ 框住, 例如‘a’字串常數(string constant) 必須以雙引號“ “ 框起, 例如“Hello!”. 字串常數的定義會影響它所儲存的記憶體位址, 如下char *cp = “one” ; // C 編譯器會發出錯誤const char *sptr = “Hello” ; // “Hello” 儲存在程式記憶體(PROM) 常數型的變數或陣列(array)必須要設定其值, 否則C 編譯器會發出錯誤訊息,如上例4.3.9指標(pointer) 與陣列(array)指標本身是一個變數, 它的內容是另一個變數存放的位址, 類似組合語言的間接定址.在使用上, 指標必須要指到一個已定義(存放於記憶體) 的變數, 否則在程式執行時會發生錯誤. 指標的宣告格式資料型態*指標名[, *指標名,….] ; 資料型態是這個指標所指的變數的資料型態, 例如char. 指標名類似變數名, 可以在一行中, 宣告指向相同資料型態的不同指標名, 例如char *tptr, *array_ptr ;int *line_ptr ;以上只是宣告指標變數, 必須要將這些指標指向已定義的變數才能使用指標的運算子& 與*運算子& 如果緊鄰在變數的前面, 例如&line, 則是代表取得此變數的記憶體位址例如,int line ; // 定義變數int *line_ptr ; // 宣告指標line = 12 ;line_ptr = &line ;若變數line 被安置於RAM 的位址64, 則指標line_ptr 等於64運算子* 緊鄰指標變數之前是表示取得這個指標指到的變數的內容, 承上例, int total ; // 定義變數total = *line_ptr ; // 取得指標line_ptr 所指到的變數line 的內容則變數total 等於12指標的大小會根據微控制器具有之記憶體空間大小而定, 如果微控制器具有一個以上的RAM bank, 則指標本身會使用兩個位元組來儲存被指到的變數的位址如果變數有const 或constant 修飾詞, 則是指向程式記憶體(PROM), 而且此變數的內容不能被修改. 如果所指向的變數不具有const 或constant, 則指標會指向資料記憶體(data memory, RAM) 內的變數.陣列(array)陣列是由相同資料型態的元素組成的, 例如char array_name[32] ;是由32 個char 型態的元素組成的, 這些元素的名字是以陣列名array_name 為準, 而以索引(index) 區分各個元素, 例如array_name[3] 是第 4 個元素. 陣列的索引是正整數, 從0 開始直到元素的總個數減一, 上例中, 最後一個元素是array_name[31]. 這種資料型態在建表格(table) 時非常有用陣列也可當做指標的一種, 只是使用時格式不同, 下列範例說明指標與陣列之間的使用方法char *nptr, *fptr ; // 宣告指標char ch, tbl ; // 定義變數char table[5] = { ‘a’, ‘b’, ‘c’, ‘d’, ‘e’ } ; // 定義陣列nptr = table ; // 指標nptr 指到陣列table 的第一個元素table[0]ch = *nptr ; // 將字元‘a’ 存入變數chtbl = table[0] ; // 將字元‘a’ 存入變數tbl , 所以變數ch 與變數tbl 的內容相同fptr = &table[4] ; // 指標fptr 指到陣列table 的第5 個元素, table[4]ch = *fptr ; // 將字元‘e’ (第5 個元素) 存入變數ch 內tbl = *(nptr+4) ; // nptr 指到陣列table 的第一個元素, 加4, 所以tbl = ‘e’4.3.10結構(struct) 與等位(union)結構是一個或多個成員的集合, 每個成員的資料型態可以不同, 並且使用結構的名字去讀寫這些成員. 結構的宣告是等同於定義一個新的資料型態, 當變數宣告為一個結構的型態時, 便可用結構的名字去讀寫各成員的內容.成員的資料型態不可以使用bit 型態, 但是可以用bit-field 方式宣告成員的型態, 例如struct str_name {unsigned flag : 1 ; // 此成員放於最低位元least significant bitunsigned no_used : 7 ;unsigned stack : 5 ; // 此成員置於最高位元high bits} usage ;每個bit field 會置放於16 位元的單位內, 不會橫跨兩個16位元的單位等位(union) 的格式與結構相同, 唯一不同的是記憶體空間的分配方式. 等位是安排共用的空間來存放不同資料型態的成員. 每個成員必須要宣告其資料型態, 而等位的大小則是所有成員中佔用最大位元組(bytes)的型態大小. 每個成員的開始位址皆相同, 就是等位的位址.union union_name {char num_byte ; // 佔用1 個位元組。