完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
一、前言
记得那是刚上大一的时候,学校电子设计创新实验室的学长们自发的组织单片机技能培训,每次周末都会安排几个小时的培训,那时候自学了C语言,开始了自己的单片机之旅,记得那时候拿着个51单片机控制LED跑流水灯、做个避障小车什么的还挺好玩的,大一下学期加入了实验室,在学长的建议下积累下来了当时的一些模块代码,做成了一套属于自己的库函数,整套代码注释非常详细,都是自己当时用心一个字一个字手敲上去的,通过那段时间对51单片机的学习,接触到了各种各样的常用传感器模块和单片机威廉希尔官方网站 ,受益良多。现在很难用到51单片机了,最近又找到了这套代码,于是分享出来,大家觉得有帮助的可以自己下载。 二、工程涉及到的模块 1、较为精确的软件延时函数 2、定时器 3、中断 4、I2C协议 5、SPI协议 6、LCD1602液晶 7、LCD12864液晶 8、PCF8591 AD和DA模块 9、DS18B20温度传感器 10、DS1302时钟 11、IR红外解码 12、RS232串口通信 13、AT24C02 存储模块 14、数码管显示 15、PWM产生 16、超声波模块 17、TFT点阵屏显示 18、GUI绘图函数 19、ASCII字库显示、中文显示 20、图片显示。 21、NRF24L01 2.4G无线通信模块 22、TFT点阵屏贪吃蛇游戏 三、代码一览 这里贴上来一些代码预览一下: 外部中断 #include “interrupt.h” /**************************************************** 函数名称: Interrupt_Falling 函数简介: 配置外部中断下降沿触发函数 入口参数: Interrupt_Num 外部中断号 Interrupt_NVIC 中断优先级(NVIC_Low或NVIC_High) 出口参数: 无 其他: 下降沿触发是通常外部中断的用法,中断后要处 理的数据自己在exti.c中编写。 *****************************************************/ void Interrupt_Falling(u8 Interrupt_Num,NVIC_Select Interrupt_NVIC) { if(Interrupt_Num==0) { IT0=1; //下降沿触发 EX0=1; //开中断0 EA=1; //开总中断 PX0=Interrupt_NVIC; //外部中断0优先级 1高优先级,0低优先级 } else { IT1=1; //下降沿触发 EX1=1; //开中断1 EA=1; //开总中断 PX1=Interrupt_NVIC; //外部中断1优先级 1高优先级,0低优先级 } } /**************************************************** 函数名称: Interrupt_Stop 函数简介: 禁止中断函数 入口参数: Interrupt_Num 外部中断号 出口参数: 无 其他: 无 *****************************************************/ void Interrupt_Stop(u8 Interrupt_Num) { if(Interrupt_Num==0) { EX0=0; //关中断0 } else { EX1=0; //关中断1 } } LCD1602 #ifndef _LCD1602_H #define _LCD1602_H #include “public.h” /***********管脚定义**********************************************/ ***it LCD1602_E=P2^7; ***it LCD1602_RS=P2^6; ***it LCD1602_RW=P2^5; #define LCD1602_Dataport P0 /**********宏定义命令控制*****************************************/ #define Com_ClearScreen 0x01 //清显示 #define Com_CursorReturn 0x02 //光标返回 #define Com_CursorAndDisplayMode 0x40 //置输入模式 #define Com_DisplayOnOff 0x80 //显示开/关控制 #define Com_CursorOrDisplayMove 0x10 //光标或字符移位 #define Com_SetFuntion 0x20 //置功能 #define Com_SetRamAdd 0x40 //置字符发生存贮器地址 #define Com_SetDDRamAddr 0x80 //置数据存贮器地址 /***********函数声明*****************************************/ void LCD1602_CheckBusy(void); //判忙函数 void LCD1602_WriteCom(uchar com); //写命令函数 void LCD1602_WriteDat(uchar dat); //写数据函数 void LCD1602_WriteAddress(uchar x,uchar y); //写地址函数 void LCD1602_WriteString(uchar x,uchar y,uchar *str); //写字符串函数 void LCD1602_Init(void); //初始化函数 #endif #include “LCD1602.h” /**************************************************** 函数名称: LCD1602_CheckBusy 函数简介: 判忙函数 入口参数: 无 出口参数: 无 其他: 无 *****************************************************/ void LCD1602_CheckBusy(void) { LCD1602_Dataport=0x00; LCD1602_E=0; LCD1602_RS=0; LCD1602_RW=1; LCD1602_E=1; while(LCD1602_Dataport&0x80); LCD1602_E=0; } /**************************************************** 函数名称: LCD1602_WriteCom 函数简介: 写命令函数 入口参数: com,待写入命令 出口参数: 无 其他: 无 *****************************************************/ void LCD1602_WriteCom(uchar com) { LCD1602_CheckBusy(); LCD1602_E=0; LCD1602_RS=0; LCD1602_RW=0; LCD1602_Dataport=com; LCD1602_E=1; delay_ms(5); LCD1602_E=0; } /**************************************************** 函数名称: LCD1602_WriteDat 函数简介: 写数据函数 入口参数: dat,待写入数据 出口参数: 无 其他: 无 *****************************************************/ void LCD1602_WriteDat(uchar dat) { LCD1602_CheckBusy(); LCD1602_E=0; LCD1602_RS=1; LCD1602_RW=0; LCD1602_Dataport=dat; LCD1602_E=1; delay_ms(5); LCD1602_E=0; } /**************************************************** 函数名称: LCD1602_WriteAddress 函数简介: 写地址函数 入口参数: x列地址0~15,y行地址0~1 出口参数: 无 其他: 无 *****************************************************/ void LCD1602_WriteAddress(uchar x,uchar y) { if(y==0) x+=0x80; else x+=0xc0; LCD1602_WriteCom(x); } /**************************************************** 函数名称: LCD1602_WriteString 函数简介: 写字符串函数 入口参数: x列地址0~15,y行地址0~1,str待写入字符 串地址指针 出口参数: 无 其他: 注意计算好对应的显示位数,避免字符写入错 误的地址 *****************************************************/ void LCD1602_WriteString(uchar x,uchar y,uchar *str) { LCD1602_WriteAddress(x,y); while(*str!=0) { LCD1602_WriteDat(*str); str++; } } /**************************************************** 函数名称: LCD1602_Init 函数简介: 初始化函数 入口参数: 无 出口参数: 无 其他: 无 *****************************************************/ void LCD1602_Init(void) { LCD1602_WriteCom(0x38); //开显示 LCD1602_WriteCom(0x0c); //开显示不显示光标 LCD1602_WriteCom(0x06); //写一个指针加1 LCD1602_WriteCom(0x01); //清屏 LCD1602_WriteCom(0x80); //设置数据指针起点 } IR红外解码 #ifndef _IR_H #define _IR_H #include “public.h” /*************管脚定义***************************************/ ***it IR_DP=P3^2; //红外传感器数据线 /*************变量定义***************************************/ extern u8 IR_OK; //红外信号接收完成标志 extern u8 IR_Dat[4]; //存储红外解码的数据(用户码,用户反码,数据码,数据反码) /*************函数声明***************************************/ void delay800us(void); //延时函数 void IR_Init(void); //红外接收初始化函数 //void IR_Interrupt0() interrupt 0; //外部中断0中断服务函数 #endif #include “IR.h” /**************************************************** 注意:红外接收头信号线发出的电平信号和接收的是相反的 即接收到的红外信号编码其实和遥控发出来的红外信 号是各位取反的关系。 *****************************************************/ u8 IR_OK=0; //红外信号接收完成标志 u8 IR_Dat[4]={0,0,0,0}; //存储红外解码的数据(用户码,用户反码,数据码,数据反码) /**************************************************** 函数名称: delay800us 函数简介: 延时函数 入口参数: 无 出口参数: 无 其他: 800us延时可以区分出信号0和1 *****************************************************/ void delay800us(void) { unsigned char a,b,c; for(c=1;c》0;c--) for(b=2;b》0;b--) for(a=197;a》0;a--); } /**************************************************** 函数名称: IR_Init 函数简介: 红外接收初始化函数 入口参数: 无 出口参数: 无 其他: 调用此函数对红外接收做好配置,注意每接收一 次红外数据都要初始化一次(调用一次该函数) *****************************************************/ void IR_Init(void) { u8 i; IR_DP=1; //先把红外传感器数据线拉高 IT0=1; //中断0,下降沿触发 EX0=1; //开中断0 EA=1; //开总中断 for(i=0;i《4;i++) { IR_Dat=0; //清除红外数据,注意一定要清除,否则中断中用移位的方式接收数据时会出错。 } IR_OK=0; //接收完成标志置0(未接收) } /**************************************************** 函数名称: IR_Interrupt0 函数简介: 外部中断0中断服务函数 入口参数: 无 出口参数: 无 其他: 调用此函数进行红外解码,注意使用红外解码时 在exti.c中注释掉相应的外部中断0,避免冲突 *****************************************************/ void IR_Interrupt0() interrupt 0 { u8 i; u16 temp; //等待时间控制变量 if(IR_DP==0&&IR_OK==0) //如果红外接收头数据线确实是低电平且红外数据未接收 { EX0=0; //关外部中断0,防止中断不断进入 while(!IR_DP) //等待9ms的低电平过去 { temp++; if(temp》10000) //如果等待时间超出正常范围,直接退出中断,避免程序死在这里 { EX0=1; //接收到错误信号后要重新打开中断,否则下次接收不了红外信号 return; } } temp=0; while(IR_DP) //等待4.5ms的高电平过去 { temp++; if(temp》10000) //如果等待时间超出正常范围,直接退出中断,避免程序死在这里 { EX0=1; //接收到错误信号后要重新打开中断,否则下次接收不了红外信号 return; } } temp=0; for(i=0;i《32;i++) { IR_Dat[i/8]》》=1; //数据是从低位开始发送的,所以向右移位 while(!IR_DP) //等待0.56ms低电平过去,因为数据0和1前部分都是0.56ms低电平,无区分度 { temp++; if(temp》10000) //如果等待时间超出正常范围,直接退出中断,避免程序死在这里 { EX0=1; //接收到错误信号后要重新打开中断,否则下次接收不了红外信号 return; } } temp=0; delay800us(); if(IR_DP==1) //800us过去,IR_DP为1则是信号1,为0则是信号0 { IR_Dat[i/8]|=0x80; //读取计数次数,存入数组中 while(IR_DP) { temp++; if(temp》10000) //如果等待时间超出正常范围,直接退出中断,避免程序死在这里 { EX0=1; //接收到错误信号后要重新打开中断,否则下次接收不了红外信号 return; } } temp=0; } } if(i==32) //如果接收数据是32位完整的,表明是红外信号 { for(i=0;i《4;i++) { IR_Dat=~IR_Dat; //数据取反,因为直接从红外接收头读到的信号与遥控的信号是各位取反的 } IR_OK=1; //数据接收完成 } } } RS232串口通信 #ifndef _RS232_H #define _RS232_H #include “public.h” void RS232_Init(u16 Baudrate); //串口通信初始化函数 #endif #include “RS232.h” /**************************************************** 函数名称: RS232_Init 函数简介: 串口通信初始化函数 入口参数: Baudrate 通信波特率 出口参数: 无 其他: 注意晶振频率为11.0592MHZ使用串口通信后定 时器1被占用,串口通信中断向量号为4。 *****************************************************/ void RS232_Init(u16 Baudrate) { SCON = 0x50; // 设定通信方式为方式1,允许接收,相当于SM1 = 1; REN = 1;(注意顺序不能颠倒!) PCON = 0x00; //SMOD=0,该语句可去掉(波特率正常),若SMOD=1则(波特率加倍) TMOD = 0x20; //设置TI定时器于工作方式2 switch (Baudrate) //确定波特率 { case 300: {TH1 = 0xA0;TL1 = 0xA0;} break; case 600: {TH1 = 0xD0;TL1 = 0xD0;} break; case 1200: {TH1 = 0xE8;TL1 = 0xE8;} break; case 2400: {TH1 = 0xF4;TL1 = 0xF4;} break; case 3600: {TH1 = 0xF8;TL1 = 0xF8;} break; case 4800: {TH1 = 0xFA;TL1 = 0xFA;} break; case 7200: {TH1 = 0xFC;TL1 = 0xFC;} break; case 9600: {TH1 = 0xFD;TL1 = 0xFD;} break; case 14400: {TH1 = 0xFE;TL1 = 0xFE;} break; case 28800: {TH1 = 0xFF;TL1 = 0xFF;} break; } TR1 = 1;//启动定时器1 EA = 1;//开总中断 ES = 1;//开串行口中断 } 超声波传感器 #ifndef _ChaoShengBo_H #define _ChaoShengBo_H #include “public.h” /*************管脚定义**********************************************/ ***it ChaoShengBo_TRIG=P2^0; //触发控制信号输入 ***it ChaoShengBo_ECHO=P2^1; //回响信号输出 /*************变量声明**********************************************/ extern u8 ChaoShengBo_Flag; //定时器中断溢出标志 /*************函数声明**********************************************/ u16 ChaoShengBo_Measure(void); //超声波测距函数 #endif #include “ChaoShengBo.h” u8 ChaoShengBo_Flag=0; //定时器中断溢出标志 /**************************************************** 函数名称: ChaoShengBo_Measure 函数简介: 超声波测距函数 入口参数: 无 出口参数: 0 测量失败 非0 测得的返回信号时间(单位us) 其他: 测试距离=(高电平时间×声速(340M/S))/2,该函数 测量返回值为时间(单位us),需要转换成怎样的 精度自己转换一下就可以了。 注意:该函数调用时占用定时器0,请在(public.h) 中使能相关的宏定义,失能其余的宏定义。 *****************************************************/ u16 ChaoShengBo_Measure(void) //0.17毫米每微秒 { u16 i=20; ChaoShengBo_Flag=0; //定时器溢出标志位清0 TR0=0; TMOD=0x11; //定时器0工作方式1,16位计数器 TH0=TL0=0; EA=1; ChaoShengBo_TRIG=1; while(i--); //只要保持10us以上即可启动一次信号发送 ChaoShengBo_TRIG=0; while(ChaoShengBo_ECHO==0); //等待低电平过去,加上i做判断防止程序死在这里 TR0=1; //高电平到来,开启定时器测量 while(ChaoShengBo_ECHO==1); //定时器测量期间程序一直等待,加上i做判断防止程序死在这里 TR0=0; //测量完成,关闭定时器 if(ChaoShengBo_Flag!=1) //若定时器未溢出 { return TH0*256+TL0; //返回测量值按12M晶振算,单位是us } else //若定时器溢出按理为65536*340/2/1000000=11.14112米,超出测量范围2cm~400cm { return 0; //定时器已经溢出,返回最大值表示测量失败 } } |
|
|
|
只有小组成员才能发言,加入小组>>
2639 浏览 0 评论
855浏览 1评论
311浏览 1评论
627浏览 0评论
356浏览 0评论
571浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-3-7 04:09 , Processed in 1.126779 second(s), Total 78, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191