1、8051 单片机 C 语言编程模板 1.函数头文件 .22.毫秒级 CPU 延时函数 .43.定时/计数器初始化函数 54.定时/计数器 1 中断处理函数 65.定时/计数器 0 中断处理函数 76.PWM 初始化函数 87.PWM0 占空比设置函数 98.UART 串口初始化函数 .109.UART 串口接收中断处理函数 .1110.UART 串口发送函数 .1211.UART 串口发送字符串函数 .1312.外部中断 INT 初始化函数 1413.外部中断 INT1 中断处理程序 1514.外部中断 INT0 中断处理程序 1515.普通 I/O 口模拟 PWM 生成程序 .1616.LC
2、D 驱动 1617.DS18B20 温度传感器驱动 1918.LCM2402(1602 也适用)驱动程序 .2119.主函数 .2520. 8 个独立式键盘驱动程序 .2721. 16 个阵列式键盘驱动程序 .281.函数头文件/*程序名: 编写人: 编写时间: 20 年 月 日硬件支持: 接口说明: 修改日志: NO.1-/*说明:/*/#include /通用 89C51 头文件(只留下实际使用的单片机所对应的头文件)#include /设定插入点#include /字符处理#include /定义错误码#include /浮点数处理#include /文件输入输出#include /参数
3、化输入输出#include /数据流输入输出#include /定义各种数据类型最值常量#include /定义本地化函数#include /定义数学函数#include /定义输入输出函数#include /定义杂项函数及内存分配函数#include /字符串处理#include /基于数组的输入输出#include /定义关于时间的函数#include /宽字符处理及输入输出#include /宽字符分类#include /51 基本运算(包括_nop_空函数)sfr 自定义名 = SFR 地址 ; /按字节定义 SFR 中的存储器名。例:sfr P1 = 0x90;sbit 自定义名 =
4、 系统位名 ; /按位定义 SFR 中的存储器名。例:sbit Add_Key = P3 1;bit 自定义名 ; /定义一个位(位的值只能是 0 或 1)例:bit LED;#define 代替名 原名 /用代替名代替原名。例:#define LED P1 / #define TA 0x25#define KEY P1 /键盘所连接的 I/O 接口组定义sbit SPEAKER = P37; /扬声器连接定义sbit DQ = P2 5; /ds18B20sbit RS = P10; /模式位,为 0 输入指令,为 1 输入数据sbit RW = P11; /读写位,为 0 读,为 1 写s
5、bit E = P12; /使能位#define Lcd_Bus P0 /数据总线unsigned char 自定义名 ; /定义一个 0255 的整数变量。unsigned int 自定义名 ; /定义一个 065535 的整数变量。data 字节寻址片内 RAM,片内 RAM 的 128 字节 (例:data unsigned char a;)bdata 可位寻址片内 RAM,16 字节,从 0x20 到 0x2F (例:bdata unsigned char a;)idata 所有片内 RAM,256 字节,从 0x00 到 0xFF (例:idata unsigned char a;)
6、pdata 片外 RAM,256 字节,从 0x00 到 0xFF (例:pdata unsigned char a;)xdata 片外 RAM,64K 字节,从 0x00 到 0xFFFF (例:xdata unsigned char a;)code ROM 存储器,64K 字节,从 0x00 到 0xFFFF (例:code unsigned char a;)2.毫秒级 CPU 延时函数/*函数名:毫秒级 CPU 延时函数调 用:DELAY_MS (?);参 数:165535(参数不可为 0)返回值:无结 果:占用 CPU 方式延时与参数数值相同的毫秒时间备 注:应用于 1T 单片机时 i
7、头文件支持。/*/void UART_TC (unsigned char *str)while(*str != 0)UART_T(*str);*str+;*str = 0;/*/中断入口说明中断入口说明interrupt 0 外部中断 0(ROM 入口地址:0x03)interrupt 1 定时/计数器中断 0(ROM 入口地址:0x0B )interrupt 2 外部中断 1(ROM 入口地址:0x13)interrupt 3 定时/计数器中断 1(ROM 入口地址:0x1B )interrupt 4 UART 串口中断(ROM 入口地址:0x23)(更多的中断依单片机型号而定,ROM 中断
8、入口均相差 8 个字节)using 0 使用寄存器组 0using 1 使用寄存器组 1using 2 使用寄存器组 2using 3 使用寄存器组 312.外部中断 INT 初始化函数/*函数名:外部中断 INT 初始化函数调 用:INT_init();参 数:无返回值:无结 果:启动外部中断 INT1、INT0 中断,设置中断方式备 注:/*/void INT_init (void)EA = 1; /中断总开关EX1 = 1; /允许外部中断 1 中断 EX0 = 1; /允许外部中断 0 中断IT1 = 1; /1:下沿触发 0:低电平触发IT0 = 1; /1:下沿触发 0:低电平触发
9、/*/13.外部中断 INT1 中断处理程序/*函数名:外部中断 INT1 中断处理程序调 用:外部引脚 INT1 中断处理 参 数:无返回值:无结 果:用户处理外部中断信号备 注:/*/void INT_1 (void) interrupt 2 using 2 /切换寄存器组到 2 /用户函数内容/*/14.外部中断 INT0 中断处理程序/*函数名:外部中断 INT0 中断处理程序调 用:外部引脚 INT0 中断处理 参 数:无返回值:无结 果:用户处理外部中断信号备 注:/*/void INT_0 (void) interrupt 0 using 2 /切换寄存器组到 2 /用户函数内容
10、/*/15.普通 I/O 口模拟 PWM 生成程序/*函数名:普通 I/O 口模拟 PWM 生成程序调 用:display (?)备 注:/*/void display (unsigned int a) /显示程序(50ms 的 PWM 宽度) DY_PORT = 0x00; /LED 小灯亮delay (a); /延时 a 的长度DY_PORT = 0xff; /LED 小灯灭delay (DY_PWM-a); /延时总 PWM 长度减 a/*/16.LCD 驱动/*/LCD 驱动(DY12864CBL 液晶显示屏并口驱动程序)/*/void chk_busy() /检查忙位(底层)RS=0
11、;RW=1;E=1;Lcd_Bus=0xff;while(Lcd_BusE=0;/*/void write_com(unsigned char cmdcode) /写命令到 LCD(底层)chk_busy();RS=0;RW=0;E=1;Lcd_Bus=cmdcode;E=0;/*/void write_data(unsigned char Dispdata) /写数据到 LCD(底层) chk_busy();RS=1;RW=0;E=1;Lcd_Bus=Dispdata;E=0;/*/void lcm_init() /初始化 LCD 屏(被调用层) write_com(0x30); /选择 8
12、bit 数据流write_com(0x0c); /开显示( 无游标、不反白)write_com(0x01); /清除显示,并且设定地址指针为 00H/*/void lcm_w_word(unsigned char *s) /向 LCM 发送一个字符串,长度 64 字符之内。 (被调用层)while(*s0) /应用:lcm_w_word(“ 您好!“);write_data(*s); s+;/*/void lcm_w_test(bit i,unsigned char word) /写指令或数据(被调用层)if(i = 0)write_com(word); /写指令或数据(0,指令)elsewr
13、ite_data(word); /写指令或数据(1,数据)/*/void lcm_clr(void) /清屏函数lcm_w_test(0,0x01);/*/17.DS18B20 温度传感器驱动/*/DS18B20 温度传感器驱动(显示 0 至 60 度)/*/void Delay(int num) /延时函数while(num-) ;/*/void Init_DS18B20(void) /初始化 ds1820unsigned char x=0;DQ = 1; /DQ 复位Delay(8); /稍做延时DQ = 0; /单片机将 DQ 拉低Delay(80); /精确延时 大于 480usDQ
14、= 1; /拉高总线Delay(14);x=DQ; /稍做延时后 如果 x=0 则初始化成功 x=1 则初始化失败Delay(20);/*/unsigned char ReadOneChar(void) /读一个字节unsigned char i=0;unsigned char dat = 0;for (i=8;i0;i-)DQ = 0; / 给脉冲信号dat=1;DQ = 1; / 给脉冲信号if(DQ)dat|=0x80;Delay(4);return(dat);/*/void WriteOneChar(unsigned char dat) /写一个字节unsigned char i=0;
15、for (i=8; i0; i-)DQ = 0;DQ = datDelay(5);DQ = 1;dat=1;/*/unsigned int ReadTemperature(void) /读取温度unsigned char a=0;unsigned char b=0;unsigned int t=0;float tt=0;Init_DS18B20();WriteOneChar(0xCC); / 跳过读序号列号的操作WriteOneChar(0x44); / 启动温度转换Init_DS18B20();WriteOneChar(0xCC); /跳过读序号列号的操作WriteOneChar(0xBE)
16、; /读取温度寄存器a=ReadOneChar(); /读低 8 位b=ReadOneChar(); /读高 8 位t=b;t=8;t=t|a;tt=t*0.0625;t= tt*10+0.5; /放大 10 倍输出并四舍五入return(t);/*/18.LCM2402(1602 也适用)驱动程序/*/ 以下是 LCM2402(1602 也适用)驱动程序 /*/*/ 引脚定义 / (使用者根据实际更改)/*/#define LCM2402_DB0_DB7 P1 / 定义 LCM2402 的数据总线sbit LCM2402_RS = P3 2; / 定义 LCM2402 的 RS 控制线sbi
17、t LCM2402_RW = P3 3; / 定义 LCM2402 的 RW 控制线sbit LCM2402_E = P3 4; / 定义 LCM2402 的 E 控制线sbit LCM2402_Busy = P1 7; / 定义 LCM2402 的测忙线(与 LCM2402_DB0_DB7 关联)/*/ 定义 LCM2402 指令集 / (详细请见技术手册)/*/#define CMD_clear 0x01 / 清除屏幕#define CMD_back 0x02 / DDRAM 回零位#define CMD_dec1 0x04 / 读入后 AC(指针)减 1,向左写#define CMD_a
18、dd1 0x06 / 读入后 AC(指针)加 1,向右写#define CMD_dis_gb1 0x0f / 开显示_开光标_开光标闪烁#define CMD_dis_gb2 0x0e / 开显示_开光标_关光标闪烁#define CMD_dis_gb3 0x0c / 开显示_关光标_关光标闪烁#define CMD_OFF_dis 0x08 / 关显示_关光标_关光标闪烁#define CMD_set82 0x38 / 8 位总线_2 行显示#define CMD_set81 0x30 / 8 位总线_1 行显示(上边行)#define CMD_set42 0x28 / 4 位总线_2 行显
19、示#define CMD_set41 0x20 / 4 位总线_1 行显示(上边行)#define lin_1 0x80 / 4 位总线_1 行显示(上边行)#define lin_2 0xc0 / 4 位总线_1 行显示(上边行)/*/ 读 LCM 忙程序 底层协议 / (所有底层协议都无需关注)/ LCM2402 测忙,若 LCM2402 处于忙状态,本函数将等待至非忙状态 /*/void LCM2402_TestBusy(void)LCM2402_DB0_DB7 = 0xff; /设备读状态LCM2402_RS = 0;LCM2402_RW = 1;LCM2402_E = 1;while
20、(LCM2402_Busy); /等待 LCM 不忙LCM2402_E = 0;/*/ 写指令程序 / 向 LCM2402 写命令 本函数需要 1 个指令集的入口参数 /*/void LCM2402_WriteCMD(uint8 LCM2402_command) LCM2402_TestBusy();LCM2402_DB0_DB7 = LCM2402_command;LCM2402_RS = 0;LCM2402_RW = 0;LCM2402_E = 1;LCM2402_E = 0;/*/ 写数据程序 / 向 LCM2402 写数据 /*/void LCM2402_WriteData(uint8
21、 LCM2402_data) LCM2402_TestBusy();LCM2402_DB0_DB7 = LCM2402_data;LCM2402_RS = 1;LCM2402_RW = 0;LCM2402_E = 1;LCM2402_E = 0;/*/ 打印字符串程序 / (本函数调用指针函数)/ 向 LCM 发送一个字符串 ,长度 48 字符之内 / 第一行位置 0x000x17 第二行位置 0x400x57 / 应用举例:print(0x80,““); /在第一行第一位处从左向右打印 字符串/*/void print(uint8 a,uint8 *str)LCM2402_WriteCMD
22、(a | 0x80);while(*str != 0)LCM2402_WriteData(*str+);*str = 0;/*/ 打印单字符程序 / / 第一行位置 0x000x17 第二行位置 0x400x57 / 向 LCM 发送一个字符 ,以十六进制(0x00)表示 / 应用举例:print(0xc0,0x30); / 在第二行第一位处打印字符“0”/*/void print2(uint8 a,uint8 t)LCM2402_WriteCMD(a | 0x80);LCM2402_WriteData(t);/*/ LCM2402 初始化 /(使用者可自定义,加 * 号程序行必须保留但可修改
23、)/*/void LCM2402_Init(void)LCM2402_WriteCMD(CMD_set82); /* 显示模式设置:显示 2 行,每个字符为 5*7 个像素LCM2402_WriteCMD(CMD_clear); / 显示清屏LCM2402_WriteCMD(CMD_back); /* 数据指针指向第 1 行第 1 个字符位置LCM2402_WriteCMD(CMD_add1); / 显示光标移动设置:文字不动,光标右移LCM2402_WriteCMD(CMD_dis_gb3); / 显示开及光标设置:显示开,光标开,闪烁开/*/19.主函数/*函数名:主函数调 用:无参 数:
24、无返回值:无结 果:程序开始处,无限循环备 注:/*/void main (void)/*函数名:扬声器驱动备 注:/*/unsigned char MUSIC; unsigned char STH0;unsigned char STL0;unsigned int code tab=64021,64103,64260,64400,/低音 3 开始 64524,64580,64684,64777, 64820,64898,64968,65030, 65058,65110,65157,65178; void main(void) TMOD=0x01; ET0=1; EA=1; KEY = 0xff
25、;while(1)STH0=tabMUSIC/256; STL0=tabMUSIC%256; TR0=1;else SPEAKER = 1;TR0=0; void t0(void) interrupt 1 using 0 TH0=STH0; TL0=STL0; SPEAKER=SPEAKER; /*/20. 8 个独立式键盘驱动程序/*函数名:8 个独立式键盘驱动程序调 用:? = Key ();参 数:无返回值:unsigned char 键值 08结 果:有键按下时返回值为键值 18,无键按下时返回值为 0备 注:在主函数中不断调用/*/unsigned char Key ( ) /8 个独立键盘处理程序unsigned char a,b;KEY = 0xff; /设定键盘初始电平状态if (KEY != 0xff) /读取键盘状态是否改变 Delay (20); /延时 20ms 去抖动if (KEY != 0xff) /重新读取 a = KEY; /寄存状态值到 aswitch(a) /键盘状态查表case 0xfe: b = 1; break;case 0xfd: b = 2; break;case 0xfb: b = 3; break;case 0xf7: b = 4; break;case 0xef: b = 5; break;case 0x