admin 管理员组

文章数量: 1086019


2024年3月6日发(作者:laravel和tp框架怎么选择)

第一课时

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();

_nop();

_nop();

//语句1

//语句2

//语句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()

{

_nop();

_nop();

}

//编写子函数的功能,LCD显示子函数,display_LCD是

//函数的名称

//这里先用空指令代表子函数的功能

//这里先用空指令代表子函数的功能

(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)

{

_nop();

_nop();

}

}

//while循环结构,当小括号里内容为真,执行while

//大括号里的内容

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) 函数的返回值及参数的介绍

① 无返回值,无参数函数:前面介绍的函数均为无返回值无参数函数。

例如:

void main()

{

}

void表示此函数是“空类型”(无返回值),void是“空”的意思,即执行

此函数后不产生一个函数值。

② 有返回值,有参数函数

例如:

程序功能说明:

参数的传递:调用函数时,程序把a赋值给x,b赋值给y;因为a和b的数据类型是u8,所以参数x和y的数据类型也是u8。

返回值 :子函数max调用完之后,通过return(z);语句把函数值z返回给主函数,即c=max(a,b);等价于c=z; ;因为c的数据类型为u8,所以函数返回值的类型也是u8。

u8 max(u8 x,u8 y)——第一个u8为函数返回值类型,其余为参数的数据类型。

#include "HT66F40.h"

#define u8 unsigned char

u8 a,b,c;

u8 max(u8 x,u8 y);

void main()

{

}

//程序中u8与unsigned char 等价

//声明变量a,b,c

//声明函数max,函数功能为比较两个数大小

a=3; //3赋值给变量a

b=4; //4赋值给变量b

while(1) //while循环结构,当小括号里内容为真,执行while大括号

{ //里的内容

_nop(); //空指令

_nop(); //空指令

c=max(a,b); //max函数调用

}

u8 max(u8 x,u8 y) //max函数功能的编写

{

u8 z;

z=x>y?x:y;

return(z);

}

③ 无返回值,有参数函数

例如:显示功能函数,

#include “ht66f40.h”

#define u8 unsigned char

u8 display_data;

void display(display_data);

void main()

{

while(1)

{

display(0x55);

}

}

void display(display_data)

{

_nop(); //显示的实际功能先用空指令代替

_nop(); //显示的实际功能先用空指令代替

}

功能说明;函数调用时,把显示的数据0x55通过参数传递给display_data;显示完毕后,并不需要返回一个函数值,因此函数的返回类型为空。

//定义变量z,只在max函数里才有效

//如果x大于y,z=x;反之,z=y;

//返回z的值给主函数

3、 常量、变量及变量的数据类型介绍

(1) 常量

① 以实际的数值出现在程序里面

例如:二进制常量 0b10101010

十进制常量 170

十六进制常量 0xAA

② 符号常量

在程序中,用一个符号来表示一个常量。

例如:#define time 50 //程序中,用time来表示50这个常量

③ 查表常量

const unsigned char tab[10]={

0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09};

——数据存放在单片机ROM里面,10代表有10个数;

——tab[0]表示第一个数,tab[1]表示第二个数……tab[9]表示第十个数。

(2) 变量及其数据类型

① 程序执行过程中,需要暂存一些数据,例如标志位,执行次数,AD采样数

据等,因此就需要定义变量来储存这些数据的。

由于变量占用ROM空间或RAM空间,因此在使用变量前,需要定义变量的数据类型,以便让编译器配置存放变量的空间。

② 基本数据类型

Size(bits)

Type(数据类型) 范围大小

bit

unsigned char

unsigned int

unsigned long

1

8

16

32

0,1

0~255或0~0xFF

0~65535或0~0xFFFF

0~4294967295或0~0xFFFFFFFF

例如:bit flag; //声明一个名称为flag的位变量

unsigned char temp1; //声明一个名称为temp1的字节变量

unsigned int temp2; //声明一个名称为temp2的双字节变量

unsigned long temp3; //声明一个名称为temp3的四字节变量

temp1=10; //变量的赋值,

temp2=0x09; //变量的赋值,

注:变量声明时,如果没有进行初始化,那么变量的值是随机的。

③ 构造数据类型

数组是指由同一种基本数据类型的数组成的一组数据。

例如:unsigned char tab[10]={}; //声明一个名称为tab的数组,它是由10

//个字节变量组成的。

//这10个变量分别是tab[0]、tab[1]……tab[9]

数组在声明时不能进行初始化,需用户在主函数里进行初始化。

例如:

unsigned char i; //声明一个字节变量

unsigned char tab[10];

for(i=0;i<10;i++)

tab[i]=0;

}

//声明一个长度为10的字节变量数组

//for循环结构,请参考下面章节

//上述代码等于tab[0]=0;tab[1]=0;……tab[9]=0

④ 变量命名规则

——第一个字符必须是英文字母或底线符号”_”,之后可紧接字母或数字。

——变量名不能超过32个字符。

——英文字母的大小写是有区别的。

例如:count,count2,_count,_count2

⑤ 变量的有效范围

——定义在函数里面,变量有效范围在此函数范围内。

——定义在函数外面,变量有效范围是整个程序。

《第一课时总结》——案例1

#include “ht66f50.h”

#define u8 unsigned char

#define u16 unsigned int

#define u32 unsigned long

#define time 50

#pragma rambank0

bit flag1;

bit flag2;

u8 i;

u8 count;

u8 temp1;

u16 temp2;

u32 temp3;

u8 tab[10];

void mcu_init();

void main(void)

{

mcu_init();

while(1)

{

flag1=0;

flag2=1;

count=time;

temp1=0xff;

temp2=0xffff;

temp3=0xffffffff;

//程序中出现u8,实际会用unsigned char代替

//程序中出现u16,实际会用unsigned int代替

//程序中出现u32,实际会用unsigned long代替

//程序中出现time,实际会用50代替

//把下面定义的变量都存放在RAM的区域0

//声明位变量flag1

//声明位变量flag2

//声明字节变量i

//声明字节变量count

//声明字节变量temp1

//声明双字节变量temp2

//声明四字节变量temp3

//声明长度为10的字节变量数组

//声明子函数,单片机初始化

//调用子函数,单片机初始化

//把0赋值给flag1

//把1赋值给flag2

//把time赋值给count,实际是把50赋值给count

//把0xff赋值给temp1

//把0xffff赋值给temp2

//把0xffffffff赋值给temp3

}

}

void mcu_init()

{

_acerl=0x00;

_cp0c=0x08;

_cp1c=0x08;

for(i=0;i<10;i++)

{

tab[i]=0;

}

}

//单片机初始化子函数的编写

//AD通道都作为普通I/O口功能

//关闭比较器0

//关闭比较器1

//数组初始化

第二课时

1、C程序架构

(1)C语言的程序是由语句所组成,每条语句的最后必须有分号“;”做为结束符。

① 函数及变量的声明语句;

例如:void mcu_init(); //声明子函数语句

bit flag1; //声明变量语句

② 表达式语句,执行数学及逻辑运算;

例如:temp1=0xff; //赋值语句

Temp1=temp1-100; //减法运算语句

temp=a||b;

temp={a&&b)>c;

表达式和表达式语句的区别:

表达式:由运算符和数据构成的式子

例如:a

a+1

a&&b

表达式语句:见前面②说明。

③ 函数调用语句,执行函数的功能

例如:mcu_init(); //子函数调用语句

④ 程序中还包含一些前置预处理指令,它们后面不需要加分号“;”作为结束符。

例如:

#include “ht66f50.h”

#define u8 unsigned char //程序中出现u8,实际会用unsigned char代替

#define time 50 //程序中出现time,实际会用50代替

#pragma rambank0 //把下面定义的变量都存放在RAM的区域0

(2)运算符

① 数学运算符

+ - * /

% 分别为加法,减法,乘法,求商,求余

比较运算符

两个数比较,如果成立,运算结果为真(1);否则,运算结果为假(0)。

> 大于 //例如a>b,如果a大于b,则结果为1;否则结果为0

>= 大于或等于 //参考上述

< 小于 //参考上述

<= 小于或等于 //参考上述

== 等于 //参考上述

!= 不等于 //参考上述

逻辑运算符

取运算符两边数据的真假值做逻辑运算,运算结果是真(1)或假(0)。

&& 与运算 //0xf0&&0x00=0;0xf0&&0x08=1;

|| 或运算 //0xf0||0x00=1; 0x00||0x00=0;

! 非运算 //!0xf0=0; !0=1;

位逻辑运算符

两个数位与位进行操作。

& 位与 //0b11111111&0b10101010=0b10101010;

//1&1=1;1&0=0;0&1=0;0&0=0;

//两个1为1,其余为0

|

^

~

位或

//0b11111111|0b10101010=0b11111111;

//1|1=1;1|0=1;0|1=1;0|0=0;

//两个0为0,其余为1

//0b11111111^0b10101010=0b01010101;

//1^1=0;1^0=1;0^0=0;

//相同为0,不同为1

//~1=0;~0=1;

//0b10101010>>1=0b01010101;右移1位

//0b10101010<<1=0b01010100;左移1位

位异或

位取反

向右移位

向左移位

>>

<<

2、程序流程控制

(1)if选择结构(2选1选择结构)

① if(条件表达式) {语句1;} //如果条件表达式为真,执行语句1;

else {语句2;} //如果条件表达式为假,执行语句2;

——小技巧:如果没有语句2,else可以忽略不写。

例如:

#include “ht66f40.h”

#define u8 unsigned char //程序中出现u8,实际会用unsigned char代替

#define u16 unsigned int

#define u32 unsigned long

#pragma rambank0

bit flag;

u8 count;

void main()

{

flag=1; //把1赋值给位变量flag

while(1)

{

if(flag!=1) //如果位变量flag不等于1

{

count=2; //执行把2赋值给字节变量count

}

}

}

else

{

count=3;

}

//如果位变量flag等于1

//执行把3赋值给字节变量count

② if语句嵌套:要注意哪个括号是属于哪个if或else的

格式:

if(表达式1) //如果表达式1为真,执行if大括号里的内容

{ //即执行语句1和第二个if语句

语句1;

if(表达式2) //如果表达式2为真,执行if大括号里的内容

{ //即执行语句2

语句2;

}

else

{

语句3;

}

}

else

{

}

语句4;

//如果表达式2为假,,执行else大括号里的内容

//即执行语句3

//如果表达式1为假,执行else大括号里的内容

//即执行语句4

(2)switch(表达式) //多选1选择结构

case 常量表达式1:语句1;break;

case 常量表达式2:语句2;break;

case 常量表达式3:语句3;break;

……

default: break; //其他

功能说明:根据switch后面括号表达式的值来选择执行哪一个case后面的语

句,执行到break;程序会跳出switch结构。

例如:

#include “ht66f50.h”

#define u8 unsigned char //程序中出现u8,实际会用unsigned char代替

#define u16 unsigned int

#define u32 unsigned long

#define time 50

#pragma rambank0

bit flag1;

bit flag2;

u8 count;

u8 temp1;

u16 temp2;

u32 temp3;

void mcu_init();

void main(void)

{

//把下面定义的变量都存放在RAM的区域0

//声明子函数,单片机初始化

mcu_init(); //调用子函数,单片机初始化

while(1)

{

temp1=2;

switch(temp1)

{

case 1: count=10;break; //如果temp1==1;执行

case 2: count=20;break; //如果temp1==2;执行

case 3: count=30;break; //如果temp1==3;执行

default: break; //如果temp1是其他值,执行

}

}

}

void mcu_init()

{

_acerl=0x00;

_cp0c=0x08;

_cp1c=0x08;

}

(2)循环结构

①while循环

while(表达式)

{语句;}

功能说明:判断表达式是否成立;

——成立执行语句;

——不成立跳出while循环;

例如:while(1)

{

}

②for循环

for(表达式1;表达式2;表达式3;)

{语句;}

功能说明:先执行表达式1;

判断表达式2是否成立;

——成立执行语句,执行表达式3,跳回判断表达式2是否成立;

——不成立跳出for循环;

例如:

unsigned char i; //声明一个字节变量

unsigned char tab[10]; //声明一个长度为10的字节变量数组

for(i=0;i<10;i++) //for循环结构,请参考下面章节

tab[i]=0;

}

《第二课时总结》——案例2

软件功能:用定时器实现1分钟的计时,用2位数码管显示。


本文标签: 子函数 变量 功能