单片机学习总结

时间:2024.4.5

预处理

一》宏定义:

1、不带参数:

#define 标识符 常量表达式

/*#define是宏定义命令,宏名(标识符)好习惯用大写*/

#define NIL 0x80

2、带参数:/*相当于小函数*/

#define 宏名(参数表) 字符串

/*不仅要时行字任串替换还要进行参数的替换,在宏定义时,宏名与带参数的括弧之间不应该加空格,否则将空格以后的字符串都作为替代字符串的一部分,这可是很容易出错的*/

如:#define SQ(a,b) a*b

使用:x=12;y=10;area=SQ(x,y);/*则area=12*10=120*/

二》文件包含:

#include <文件名>或#include "文件名"

/*在C中用双引用形式更保险,在C51中常用物是尖括弧形式*/ 三》条件编译:

/*一般源程序中的所有程序行都参加编译,但有时希望对其中一部分内容只在满足一定条件下才进行编译,也就是对一部分内容指定编译的条件。*/ #if、#elif、 #else、#endif、#ifdef、#ifndef

/*选择不同的编译范围,产生不同的代码,提供通用性。*/

/*如对8051在6MHZ与12MHZ下有*/

#ifdef cpu==8051

#define FREQ 6 /*程序段*/

#else

#define FREQ 12/*程序段*/

#endif

/*这样下面的原程序不用做任何修改便可以使用于两种时钟频率的单片机系统*/

四》其他:

1、#error:捕捉不可预料的编译条件

#if (myv!=0&&myv!=1)/*假定其值必为0或1*/

#error myv must be 1 or 0/*出错时显示*/

#endif

2、#pragma:用于在程序中向编译器传送各种编译控制命令

#pragma 编译命令序列

/*例:想按如下命令编译ex.c c51 ex.c debug cod large可用:*/ #pragma DB CD LA

#pragma disable

/*禁止中断*/

单片机C语言之二

_____________________________________________________________________________________

一》数据类型:

char int long

1:unsinged 0~255 0~65535 0~4294967295

2:signed -128~127 -32768~32767 -2147483648~2147483647 指针:* 3字节

位标量: sbit

特殊功能寄存器:sfr

16位特殊功能寄存器:sfr16 占2个内存单元,0~65535

可寻址位:sbit利用他可访问51单片机的内部RAM中的可寻址位或特殊功能寄存器中的可寻址位

sfr P0=0x80;

sbit P0_1=P0^1;

/*将P0口的口地址定义为80H,将P0.1位定义为P1_1*/

二》数据存贮类型

表1. C51数据存贮类型

━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━ 数据存贮类型 ┃ 与存贮空间的对应关系

━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━ data ┃ 直接寻址片内数据存贮区,访速度

bdata ┃ 可位寻址片内数据存贮区,允许位与字节混合访问 idata ┃ 间接寻址片内数据存贮区,可访问片内全部RAM地址空间

pdata ┃ 分页寻址片外数据存贮区(256字节)由MOVX @R0访问

xdata ┃ 片外数据存贮区(64K),由MOVX @DPTR访问

code ┃ 代码存贮区(64K),由MOVC @DPTR访问

━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━━ 变量的存贮类型定义:

char data var

/*字符变量var被定义为data存贮类型,C51编译器将把该变量定位在51单片机片内数据区存贮区中*/

bit bdata flag

/*位变量flag被定义为bdata存贮类型,C51编译器将把该变量定位在51单片机片内数据区存贮区(RAM)中的位寻址区:20H--2FH*/

三》typedef:重新定义数据类型

typedef 已有数据类型 新的数据类型

typedef int word;

/*将word定义为整型*/

word i,j;

/*将i,j定义为整型*/

四》位运算符:

━━━━┳━━━━━┳━━━━━┳━━━━━━┳━━━━━━┳━━━━━━

~ ┃ & ┃ | ┃ ^ ┃ << ┃ >>

━━━━╋━━━━━╋━━━━━╋━━━━━━╋━━━━━━╋━━━━━━

按位取反┃ 按位与 ┃ 按位或 ┃ 按位异或 ┃ 左移 ┃ 右移

━━━━┻━━━━━┻━━━━━┻━━━━━━┻━━━━━━┻━━━━━━

对移位:如<< ,a<<2,即为将二进制的a左移两位,若a=0x8f,即10001111,a=a<<2,将导致a=0x3c(00111100),右边补零。

五》条件运算符:

逻辑表达式? 表达式1:表达式2

六》指针与地址运算符:

*取内容 &取地址

七》强制类型转换:(类型)=表达式

(char *)0xb000

八》sizeof 取数据类型、变量以及表达式的字节数的运算符;

九》continue:中断语句:结束本次循环。

单片机C语言之三

_____________________________________________________________________________________

函数:

一》中断服务函数与寄存器组定义:

函数类型 函数名(形式参数表) [interrupt n][using n]

n为中断号,0~31:

━━━━┳━━━━━┳━━━━━

中断编号┃ 中断向量┃ 入口地址

━━━━╋━━━━━╋━━━━━

0 ┃ 外中断0 ┃ 0003H

━━━━╋━━━━━╋━━━━━

1 ┃ 定时器0 ┃ 000BH

━━━━╋━━━━━╋━━━━━

2 ┃ 外中断1 ┃ 0013H

━━━━╋━━━━━╋━━━━━

3 ┃ 定时器1 ┃ 001BH

━━━━╋━━━━━╋━━━━━

4 ┃ 串行口 ┃ 0023H

━━━━┻━━━━━┻━━━━━

后面的n指的是四个工作寄存器组的一个:0~3

对函数目标代码影响如下:

在函数入口处将当前工作寄存器组保护到堆栈中;指定的工作寄存器内容不会改变,函数返回前将被保护的工作寄存器组从堆栈中恢复!

例(定时1ms):

#include <reg51.h>

sbit P1_0=P1^0;

void timer0(void) interrupt 1 using 1{

P1_0=!P1_0;

TH0=-(1000/256);

TL0=-(1000%256);

}

main(){

SP=0x60;

P1_0=0;

TMOD=0X01;

TH0=-(1000/256);

TL0=-(1000%256);

EA=1;

ET0=1;

TR0=1;

do{}while(1);

}

/* 注意:

1、如果中断函数中用到浮点运算,必须保存浮点寄存器的状态。(在math.h中保存浮点寄存器函数为pfsave, 恢复浮点寄存器的状态函数为fprestore)

2、如果在中断函数中调用了其他函数,则被调函数所使用的工作寄存器组

与中断函数的一致!

*/

单片机C语言之四

_____________________________________________________________________________________

一、 局部变量与全局变量(外部变量):

1、 全局变量若不在开头定义则加extern

2、 全局变量会使代码长,占用内存多

二、 存储方式:

自动变量(auto):缺省,函数调用存在,退出消失。

内部变量 静态变量(static):static int a=5;始终存在,退出不消失,但不能访问。

寄存器变量(register):速度最快。通常只给编译器一个建议,由编译器根 据实际情况确定。(见下)

变量 全局变量(global):

外部变量

静态变量(static):

寄存器变量例:

#include<stdio.h>

int_power(m,e)

int m;

register int e;

{

register int temp;

temp=1;

for(;e;e--)

temp*=m;

return(temp);

}

main()

{

??

}

三、 函数的参数和局部变量的存储器模式:

三种存储器模式:small,compact,large.

一个函数的存储器模式确定了函数的参数和局部变量在内存中的地址空间 small:内部ram

compact, large:外部RAM

函数类型 函数名(形式参数表)[存储器模式]

例:

#pragma large /*默认存储器模式为large*/

extern int calc(char I,int b)small; /*指定small模式*/

extern int func(int I,float f) large; /*指定large模式*/

int large_te(int I,int k) /*未指定,按默认的large模式处理*/ {

return(mtest(I,k)+2);

}

利用存储器混合模式编程,充分利用有限的存储空间,还可加快程序的执行速度!

单片机C语言之五

_____________________________________________________________________________________

数组

1>初始化数组:

unsigned char a[5]={0x11,0x22,0x33,0x44,0x55}

unsigned char a[ ] ={0x11,0x22,0x33,0x44,0x55,0x66}

3>数组作为函数的参数:不但可以由变量作为函数的参数外,还可以用数组名作为函数的参数。一个数组数组名表示该数组的首地址。用一个数组名作为函数的参数时,在执行函数调用的过程中参数传递方式采用的是地址传递。将实际参数数组首地址传递给被调函数中的形式参数数组,这样一来两个数组就占有同一段内存单元。见下图:

a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9]

起始地址1000

b[0] b[1] b[2] b[3] b[4] b[5] b[6] b[7] b[8] b[9]

用数组名作为函数的参数,应该在主调函数和被调函数中分别进行数组定义而不能只在一方定义数组。而且在两个函数中定义的数组类型必须一致,如果类型不一致将导致编译出错。实参数组和型参数组的长度可以一致可以不一致,编译器对形参数组的长度不做检查,直只是将实参数组的首地址传递给行参数组。如果希望行参数组能得到实参数组的全部元素,则应使两个数组的长度一致。定义型参数组时可以不指定长度,只在数组名后面跟一个方括号[]。这时为了在被调函

数中处理数组元素的需要,应另外设置一个参数来传递数组元素的个数。 例:用数组作为函数的参数,计算两个不同长度的数组中所有元素的平均值 #include<stdio.h>

float average(array,n)

int n;

float array[ ];

{

int I;

float aver,sum=array[0];

for(I=1;I<n;I++)

sum=sum+array[I];

aver=sum/n;

return(aver);

}

main()

{

float pot_1[2]={99.9,88.8};

float pot_2[3]={11,22,33.3};

average(pot_1,2);

average(pot_1,3);

}

单片机C语言之六

_____________________________________________________________________________________

软件法去干扰:

工程上我们在采集数据时一般要求精度达到5%%,大于这个值将认为无效。我在实际应用中采用8535对32路数据进行采集(8535带10位AD,带看门狗),发现数据跳动有时达7%%,这是由于各种干扰造成的。主要来自于随机干扰,下面就各种干扰的方法给出简单的去除方法:

1、白噪声:最重要的统计特性为平均值为0,可采取每路数据采集几次求平均的方法;

2、随机干扰:该点明显高于或低于附近正常采样值,故采取中值滤波法,即对被测信号连续采样M次,进行大小排序,取大小居中的1/3个采样值进行算术平均;

3、电源干扰:特点是有固定周期,故可采用定时采样求平均的方法。 由于各种排序与求平均算法用C易于实现,故C常常用于采集系统中软件去干扰。至于排序算法可参考上一篇文章,有一个经典的程序。

在实际中我们采用每路猜9个值,排序,取中间3个,求平均。然后。。,每路数据几乎不动!

单片机C语言之七

_____________________________________________________________________________________

指针:可对内存地址直接操作

基于存贮器的指以贮器类为参量,它在编译时才被确定。因此为指针选择存贮器的方法可以省掉,以这些指针的长度可为1个字节(idata *,data *,pdata *)或2个这节(code *,xdata *)。

char xdata *address;

ADC0809具有8个模拟量输入通道,采用中断方式,在中断函数中读取8个通道的A/D转换值,分别存储在外部RAM的1000H~1007H单元。ADC0809端口地址为00F0H。

程序定义了两个指针变量* ADC和* ADCdata,分别指向ADC0809端口地址(00F0H)和外部RAM单元地址(1000H~1007H)

由*ADC=I送入通道数,启动ADC0809进行A/D转换,转换结束时产生INT1中断。在中断服务函数int1()中通过temp=*ADC和*ADCdata=temp;读取A/D转换结果并存到外部RAM中。

#include<reg51.h>

unsigned int xdata *ADC; /*定义ADC0809端口指针*/

unsigned int xdata *ADCdata; /*定义ADC0809数据缓冲器指针*/ unsigned char I;

void main( )

{

ADC=0x00f0; /*定义端口地址和数据缓冲器地址*/

ADCdata=0x1000;

I=8; /* ADC0809有8个模拟输入通道*/

EA=1; EX1=1;IT1=1; /*开中断*/

*ADC=I; /*启动ADC0809*/

WHILE(I); /*等待8个通道A/D转换完*/

}

void int1() interrupt 2

{

unsigned char tmp;

temp=*ADC; /*读取A/D转换结果*/

*ADCdata=temp; /*结果值存到数据缓冲区*/

ADCdata++; /*数据缓冲区地址加1*/

i—;

*ADC=I; /*启动下一个模拟输入通道A/D转换*/

}

除了用指针变量来实现对内存地址的直接操作外,c51编译器还提供一组宏,该宏定义文件为:“absacc.h”,利用它可十分方便地实现对任何内存空间的直接

操作,改写上面的程序:

#include<reg51.h>

#include<absacc.h> /*包含绝对地址操作预定义头文件*/

#define ADC 0x00f0; /*定义ADC0809端口地址*/

#define ADCdata 0X1000 /*定义数据缓冲器地址*/

unsigned char I;

void main( )

{

I=8; / *ADC0809有8个模拟输入通道*/

EA=1;ex1=1;it1=1; / *开中断*/

XBYTE[ADC]=I; /*启动0809 */

While(i); /*等待8个通道转换完毕*/

}

void int1() interrupt2 {

unsigned char tmp;

tmp=XBYTE[ADC]; /*读取A/D转换结果*/

i--;

XBYTE[ADCdata+I]=tmp; /**结果值存储到数据缓冲器*/

XBYTE[ADC]=I; /*启动下一个模拟输入通道A/D转换*/

}

两指针相减-----计算字符串的长度

#include<stdio.h>

main() {

char *s=”abcdef”;

int strlen(char *s);

printf(“\n length of ‘%%s’=%%d\n”,s,strlen(s));

}

int strlen(char *s) {

char *p=s;

while(*p!=’\0’)p++;

return(p-s);

}

结果为:length of ‘abcdef’=6

注:不允许指针之间进行加,乘,除,移位,或屏蔽运算,也不允许用float类型数据与指针做加,减运算!

抽象型指针:

ANSI新标准增加了一种“void * ”的指针类型,这是一种抽象型指针,即可以定义一个指针变量,但不指定该指针是指向哪种类型的数据的。在赋值时需进行强制类型转换:

Char *p1;

Void *p2;

P1=(char*)p2;

抽象型指针可以用来在每个存储区内访问任意绝对地址或者用来产生绝对调用。

更多相关推荐:
单片机学习总结

单片机是一门应用性和综合性很强的学科,它综合了电子技术中的模拟电路和数字电路方面的知识,特别是数字电路,因为数字电路在单片机里面的应用很多。由于单片机涉及的知识很多,所以我们只能循序渐进的学习,逐步的积累,没有…

msp430单片机学习总结

Msp430单片机学习总结:1、时钟系统配置:430单片机正常有3个时钟模块,即MCLK、SMCLK、ACLK,在我们正常使用时,应该设置为:A:ACLK来源于LFXT1CLK的低频模式自己最近刚开始接触MSP…

5年单片机学习总结

人的一生是一个不断学习、不断成长的过程。转眼间,研究生的学习生涯结束了,走上新的工作岗位。回头看看,发现自己不知不觉已经走过了五年的单片机学习之旅。在20xx年最初接触单片机的时候,在我心中觉得51就是单片机,…

51单片机学习总结

1、什么是单片机在一片集成电路芯片上集成微处理器、存储器、I/O接口电路,从而构成了单芯片微型计算机,即单片机。Intel公司推出了MCS-51系列单片机:集成8位CPU、4K字节ROM、128字节RAM、4个…

单片机学习总结

单片机假期培训总结郭林朋首先感谢领导给我这次培训的机会,通过这次培训我获益良多,提高了自己的专业技能,下面就是我对本次学习的总结和教训。第一天的开学典礼上,我们听了亚龙集团陈总经理的报告,特别是陈总经理提出的,…

5年单片机学习总结(转)

5年单片机学习总结(转)人的一生是一个不断学习、不断成长的过程。转眼间,研究生的学习生涯结束了,走上新的工作岗位。回头看看,发现自己不知不觉已经走过了五年的单片机学习之旅。在20xx年最初接触单片机的时候,在我…

5年单片机学习总结

5年单片机学习总结人的一生是一个不断学习、不断成长的过程。转眼间,研究生的学习生涯结束了,走上新的工作岗位。回头看看,发现自己不知不觉已经走过了五年的单片机学习之旅。在20xx年最初接触单片机的时候,在我心中觉…

单片机学习心得

第一节跟我学单片机到底是学什么我的两个比喻和一个规则开篇第一节我问大家一个问题跟我学单片机到底是学什么我的回答是像驾驶汽车一样驾驭单片机我教给大家的是驾驶汽车的技术而不是研发汽车的技术因此每当别人问我学51单片...

单片机学习心得

1小时c语言入门一相信很多爱好电子的朋友对单片机这个词应该都不会陌生了吧不过有些朋友可能只听说他叫单片机他的全称是什么也许并不太清楚更不用说他的英文全称和简称了单片机是一块在集成电路芯片上集成了一台有一定规模的...

学习单片机心得笔记

120xx年5月1日095048心得在protues和keil软件连调的时候每次更改keil里的程序后必须点击编译按钮才会在protues中显示效果点击保存时看不到效果的另外想要生成hex文件也必须点击编译按钮...

对单片机课程学习的感想与收获

对单片机课程学习的感想与收获老师曾说过单片机是很重要的一门课程如果学好一门单片机就凭这个技术这门手艺找一个好工作也不成问题对此我了解了一下据统计目前仅单片机设计行业至少有2030万的人才缺口仅北京市场嵌入式硬件...

单片机学习心得 (选修课)

单片机学习心得1成都理工大学学院地球物理学院专业遥感科学与技术学号姓名邮箱是否选课是单片机学习心得单片机到底是什么呢就是一个电脑只不过是微型的麻雀虽小五脏俱全它内部也用和电脑功能类似的模块比如CPU内存并行总线...

单片机学习总结(42篇)