找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3023|回复: 1
收起左侧

CX20106+4069超声波测距电路与单片机源码(带详细代码注释)

[复制链接]
ID:329250 发表于 2018-5-14 00:12 | 显示全部楼层 |阅读模式
0.png
超声波测距IC模块电路原理图如下:
0.png

单片机源程序如下:
  1. /*
  2. * 超声波测距模块(CX20106+4069版本)
  3. *
  4. * 用途:超声波测距模块测试程序
  5. *
  6. * 作者                                        日期                                备注
  7. * Huafeng Lin                        20011/01/05                        新增
  8. * Huafeng Lin                        20011/01/05                        修改
  9. *
  10. */

  11. #include<reg51.h>
  12. #include<INTRINS.H>

  13. #define uchar unsigned char
  14. #define uint  unsigned int

  15. #define        nop                        _nop_()

  16. #define LCM_Data     P2    //数据接口
  17. #define Busy         0x80   //用于检测LCM状态字中的Busy标识

  18. uint        dis;
  19. uchar        flag=0,high_time,low_time;

  20. sbit         in=P3^3;        //外部中断1,接CX20106的7脚
  21. sbit         csb=P1^0;        //40KHz方波输出脚

  22. sbit    LCM_RW     = P0^1;  //读写控制输入端,LCD1602的第五脚
  23. sbit    LCM_RS     = P0^2;  //寄存器选择输入端,LCD1602的第四脚
  24. sbit    LCM_E      = P0^0;  //使能信号输入端,LCD1602的第6脚

  25. void    WriteDataLCM                (uchar WDLCM);                //LCD模块写数据
  26. void    WriteCommandLCM        (uchar WCLCM,BuysC);         //LCD模块写指令
  27. uchar   ReadDataLCM                (void);                //LCD模块读数据
  28. uchar   ReadStatusLCM        (void);                //读LCD模块的忙标
  29. void    DisplayOneChar   (uchar X,uchar Y,uchar ASCII);                //在第X+1行的第Y+1位置显示一个字符
  30. void    DisplayListChar  (uchar X,uchar Y,uchar delayms,uchar code *DData);
  31. void    DisplayCursorPos (uchar X, uchar Y);
  32. void    LCMInit          (void);
  33. void    DisplayIntData   (uchar X, uchar Y,int ZhengShu,uchar Digit,uchar XiaoShu);
  34. void    DisplayCharData  (uchar X, uchar Y,uchar ZiFu);

  35. void DelayUs(uint us);
  36. void DelayMs(uint Ms);

  37. void         init(void);                        //初始化
  38. void         delay_nms(uint n);        //延时nms
  39. void         display(uint dat);        //显示函数
  40. void         tran(void);                        //发射超声波
  41. void         delay100us();                //延时100us

  42. /**********************************
  43. 函数名称:初始化函数
  44. 修改日期:
  45. 入口参数:无
  46. 返回值:  无
  47. **********************************/
  48. void init(void)
  49. {
  50.            TMOD=0x01;//定时器0方式1用于计时,定时器1用于产生38K方波
  51.         TH0=0;
  52.         TL0=0;                /* 设定T0的工作模式为2*/
  53.         EA=1;
  54.         IT1=1;//下降沿有效,左传感器
  55. }
  56. /**********************************
  57. 函数名称:延时函数
  58. 修改日期:
  59. 入口参数:n
  60. 返回值:  无
  61. **********************************/
  62. void delay_nms(uint n)
  63. {
  64.          uchar i;
  65.       while(n--)
  66.       {
  67.           for(i = 0; i < 123; i++);
  68.        }                                ;
  69. }
  70. /************************************************
  71. 延时100us函数
  72. ***********************************************/
  73. void delay100us()
  74. {
  75.         uchar j;
  76.         for(j=50;j>0;j--);
  77. }
  78. /**********************************
  79. 函数名称:超声波发射函数
  80. 修改日期:
  81. 入口参数:无
  82. 返回值:  无
  83. **********************************/
  84. void tran(void)
  85. {
  86.         uchar i;
  87.         float temp;
  88.         TH0=0;
  89.         TL0=0;//清定时0
  90.         TR0=1;//开定时0
  91.         for(i=8;i>0;i--)
  92.         {
  93.                 csb=!csb;
  94.                 //nop;
  95.                 //nop;
  96.                 nop;
  97.                 nop;
  98.                 nop;
  99.                 nop;
  100.                 nop;
  101.                 nop;
  102.                 nop;
  103.                 nop;
  104.         }
  105.         csb=1;
  106.         delay_nms(1);//延时1ms左右后再开中断,避免直接回来的回波
  107.         EX1=1;
  108.         delay_nms(50);
  109.         if(flag==1)
  110.         {
  111.                 temp=high_time*256+low_time;
  112.                 temp=(temp/1000)/2;
  113.                 temp*=344;
  114.                 temp=temp/10;
  115.                 //if(temp>10)
  116.                 dis=(unsigned int)temp;
  117.                 flag=0;
  118.         }
  119.         //else dis=0;
  120. }
  121. /**********************************
  122. 函数名称:中断函数
  123. 修改日期:
  124. 入口参数:无
  125. 返回值:  无
  126. **********************************/
  127. void TT() interrupt 2
  128. {
  129.         uint tmp;
  130.         TR0=0;//关定时器0
  131.         ET1=0;//关外部中断
  132.         //flag=1;//外部中断标志位
  133.         tmp=TH0*256+TL0;
  134.         if((tmp>0)&&(tmp<60000))        
  135.         {
  136.                 high_time=TH0;
  137.                 low_time=TL0;
  138.                 flag=1;        
  139.         }
  140.         else
  141.         {
  142.                 high_time=0;
  143.                 low_time=0;        
  144.         }
  145. }

  146. /*===========================================================================
  147. 主程序
  148. =============================================================================*/
  149. void main(void)
  150. {
  151.         uchar i;
  152.         uint tp=0;
  153.         init();
  154.         LCMInit();
  155.         DisplayOneChar(1,10,'M');
  156.         DisplayListChar(0,0,0,"LCSOFT (C) 2011");
  157.         while(1)
  158.         {
  159.                 tran();
  160.                 for(i=100;i>0;i--)
  161.                 {
  162.                         DisplayIntData(1,9,dis,4,2);
  163.                 }         
  164.         }
  165. }         
  166. /*====================================================================  
  167. 功 能:    在1602显示一个整数数据
  168. 说 明:    显示一个整数数据-9999->32625.  从右至左显示数据5位:   
  169. ======================================================================*/
  170. void DisplayIntData(uchar X, uchar Y,int ZhengShu,uchar Digit,uchar XiaoShu)
  171. {
  172.       uchar i=0,k=0, BCD[5]={0};
  173.           if(Digit>5)  Digit=5;
  174.       if(ZhengShu<0)
  175.           {
  176.          k=1;//负数示志位
  177.          ZhengShu=-ZhengShu;
  178.           }
  179.       BCD[4]  =  ZhengShu / 10000;         //求出万位数据
  180.       ZhengShu = ZhengShu % 10000;
  181.       BCD[3]  =  ZhengShu / 1000;          //求出千位数据
  182.       ZhengShu = ZhengShu % 1000;
  183.       BCD[2]  =  ZhengShu / 100;           //求出百位数据
  184.       ZhengShu = ZhengShu % 100;
  185.       BCD[1]  =  ZhengShu / 10;            //求出十位数据
  186.       BCD[0]  =  ZhengShu % 10;            //求出个位数据
  187.          
  188.       for(i=0;i<Digit;i++)//输出显示的数值
  189.       {   
  190.                if((i==XiaoShu)&&(0!=XiaoShu))
  191.                    {  
  192.                       DisplayOneChar(X,Y-i,'.');//输出小数点
  193.                           Y= Y-1;
  194.                     }
  195.                         
  196.                DisplayOneChar(X,Y-i,BCD[i]+0x30); //显示一个字符
  197.           }
  198.       if(k==1)
  199.           DisplayOneChar(X,Y-1,'-');//输出负符
  200. }
  201. /*====================================================================
  202. 功 能:在1602显示一个字符数据
  203. 说 明:显示一个字符数据0~256.  从左至右显示数据3位
  204. ======================================================================*/
  205. void DisplayCharData(uchar X, uchar Y,uchar ZiFu)
  206. {
  207.       uchar i=0;
  208.       uchar ValueBCD[3];
  209.       ValueBCD[0]  = ZiFu / 100;           //求出百位数据
  210.               ZiFu = ZiFu % 100;
  211.       ValueBCD[1]  = ZiFu / 10;            //求出十位数据
  212.       ValueBCD[2]  = ZiFu % 10;            //求出个位数据
  213.          
  214.       for(i=0;i<3;i++)//输出显示的数值
  215.       {         
  216.                DisplayOneChar(X,Y+i,ValueBCD[i]+0x30); //显示一个字符
  217.           }
  218. }
  219. /*======================================================================
  220. LCM初始化
  221. ======================================================================*/
  222. void LCMInit(void)
  223. {
  224. LCM_Data = 0;
  225. WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号
  226. DelayMs(5);
  227. WriteCommandLCM(0x38,0);
  228. DelayMs(5);
  229. WriteCommandLCM(0x38,0);
  230. DelayMs(5);
  231. WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号
  232. WriteCommandLCM(0x08,1); //关闭显示
  233. WriteCommandLCM(0x01,1); //显示清屏
  234. WriteCommandLCM(0x06,1); // 显示光标移动设置
  235. WriteCommandLCM(0x0C,1); // 显示开及光标设置

  236. DelayMs(100);
  237. }
  238. /*====================================================================
  239.    显示光标的位置
  240. ====================================================================*/
  241. void DisplayCursorPos( unsigned char X, unsigned char Y)
  242. {
  243. X &= 0x1;
  244. Y &= 0xF; //限制Y不能大于15,X不能大于1
  245. if (X) Y |= 0x40; //当要显示第二行时地址码+0x40;
  246. Y |= 0x80; // 算出指令码
  247. WriteCommandLCM(Y, 1); //这里不检测忙信号,发送地址码
  248. }
  249. /*====================================================================  
  250.   按指定位置显示一串字符:第 X 行,第 y列
  251.   注意:字符串不能长于16个字符
  252. ======================================================================*/
  253. void DisplayListChar(uchar X,uchar Y,uchar delayms, uchar code *DData)
  254. {
  255. unsigned char ListLength;

  256. ListLength = 0;

  257. X &= 0x1;
  258. Y &= 0xF; //限制X不能大于15,Y不能大于1
  259. while (DData[ListLength]!='\0') //若到达字串尾则退出
  260.   {
  261.      if (Y <= 0xF) //X坐标应小于0xF
  262.      {
  263.         DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符
  264.         ListLength++;
  265.         Y++;
  266.             DelayMs(delayms);//延时显示字符串
  267.      }
  268.      else
  269.             break;//跳出循环体
  270.   }
  271. }
  272. /*====================================================================
  273.   设定延时时间:x*1us
  274. ====================================================================*/
  275. void DelayUs(uint us)
  276. {
  277.     while(us--);
  278. }
  279. /*====================================================================
  280.   设定延时时间:x*1ms
  281. ====================================================================*/
  282. void DelayMs(uint Ms)
  283. {
  284.   uint i,TempCyc;
  285.   for(i=0;i<Ms;i++)
  286.   {
  287.     TempCyc = 250;
  288.     while(TempCyc--);
  289.   }
  290. }                                 
  291. /*=====================================================================
  292. 写数据函数: E =高脉冲 RS=1 RW=0
  293. ======================================================================*/
  294. void WriteDataLCM(unsigned char WDLCM)
  295. {
  296. ReadStatusLCM(); //检测忙
  297. LCM_Data = WDLCM;
  298. LCM_RS = 1;
  299. LCM_RW = 0;
  300. LCM_E = 0; //若晶振速度太高可以在这后加小的延时
  301. LCM_E = 0; //延时
  302. LCM_E = 1;
  303. }
  304. /*====================================================================
  305.   写指令函数: E=高脉冲 RS=0 RW=0
  306. ======================================================================*/
  307. void WriteCommandLCM(unsigned char WCLCM,BuysC) //BuysC为0时忽略忙检测
  308. {
  309. if (BuysC) ReadStatusLCM(); //根据需要检测忙
  310. LCM_Data = WCLCM;
  311. LCM_RS = 0;
  312. LCM_RW = 0;
  313. LCM_E = 0;
  314. LCM_E = 0;
  315. LCM_E = 1;
  316. }
  317. /*====================================================================
  318. //读数据
  319. ======================================================================*/
  320. unsigned char ReadDataLCM(void)
  321. {
  322. LCM_RS = 1;
  323. LCM_RW = 1;
  324. LCM_E = 0;
  325. LCM_E = 0;
  326. LCM_E = 1;
  327. return(LCM_Data);
  328. }
  329. /*====================================================================
  330.   正常读写操作之前必须检测LCD控制器状态:E=1 RS=0 RW=1;
  331.   DB7: 0 LCD控制器空闲,1 LCD控制器忙。
  332.   读状态
  333. ======================================================================*/
  334. unsigned char ReadStatusLCM(void)
  335. {
  336. LCM_Data = 0xFF;
  337. LCM_RS = 0;
  338. LCM_RW = 1;
  339. LCM_E = 0;
  340. LCM_E = 0;
  341. LCM_E = 1;
  342. while (LCM_Data & Busy); //检测忙信号  
  343. return(LCM_Data);
  344. }
  345. /*======================================================================
  346. 功 能:     在1602 指定位置显示一个字符:第一行位置0~15,第二行16~31
  347. 说 明:     第 X 行,第 y 列  注意:字符串不能长于16个字符
  348. ======================================================================*/
  349. void DisplayOneChar( unsigned char X, unsigned char Y, unsigned char ASCII)
  350. {
  351. X &= 0x1;
  352. Y &= 0xF; //限制Y不能大于15,X不能大于1
  353. if (X) Y |= 0x40; //当要显示第二行时地址码+0x40;
  354. Y |= 0x80; // 算出指令码
  355. WriteCommandLCM(Y, 0); //这里不检测忙信号,发送地址码
  356. WriteDataLCM(ASCII);
  357. }
复制代码

所有资料51hei提供下载:
超声波测距LC模块.rar (317.06 KB, 下载次数: 61)
回复

使用道具 举报

ID:354404 发表于 2018-8-13 21:40 | 显示全部楼层
为什么我做出来测出来没有用啊
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表