基于51单片机电子指南针设计

1、设计需求及目标

通过对电子指南针硬件电路和软件程序的分析,阐述了电子指南针基本的工作原理及实现。实现模块精度达到1°,能够在LCD上显示当前方位并能通过键盘控制上传指南针处理得到的数据到上位机。

2、设计思路及方案

电子指南针的系统主要由前端磁阻传感器、磁场测量专用转换芯片、单片控制器、辅助扩展电路、人机界面以及系统电源几个部分组成,系统结构如图:

整个系统中前端的磁阻传感器负责测量地磁场的大小并将磁场的变化转化为微弱的电流的变化,专用的磁场测量芯片负责把磁阻传感器变化的电流(模拟量)转换成微控制器可以识别的数字量,然后通过芯片内部的SPI总线上传给微控制器。微控制器将表征当前磁场大小的数字量按照方位进行归一化等处理后通过直观的LCD进行方位显示,同时可以通过键盘控制微控制器进行相应的操作,如将转换后的数据通过串口的形式发送到上位机。整个系统中还包含了实时时钟等一些辅助电路,使整个系统功能得到进一步的扩展。仿真电路图:

3、 部分代码

/******************************************************************************************************************************
***模块名称: 测试主程序                                                                                                    ***
***模块功能:                                                                                                               ***																				                       
***作    者: METAL MAX,CUIT([email protected])                                                                             ***
***调用方式:                                                                                                               ***
***日    志: 日期             版本                     修改人                               记录                           ***
***           06/10/2008       V1.01                    METALMAX                       总体组合测试通过                     ***
***备    注:                                                                                                               ***
*****************************************************************************************************************************/
#include <reg52.h>
#include <stdio.h>
#include <math.h>                                                       /* T6963驱动库                                      */
#include "DriverT6963.h"
#include "DataBase.h"
#include "PCF8583.h"
#include "UART.h"

unsigned char GblCnt = 0;
unsigned char T0IRQCNT = 0;
unsigned char oldtempx, oldtempy;
unsigned int Angle;
unsigned char keyflag = 0;
extern unsigned char COMBUF[10];
/******************************************************************************************************************************
**函数名称:delay()                                                                                                          **
**函数功能:软件延迟                                                                                                         **   
**入口参数:延迟时间倍数                                                                                                     **
**出口参数:无                                                                                                               **
**具体资源:无                                                                                                               **
**调用程序:无                                                                                                               **
**备    注:延时不精确                                                                                                       **
******************************************************************************************************************************/
void delay(unsigned int time)
{
   unsigned int i,j;
   for (i=0; i<time; i++) {
     for (j=0; j<1700; j++){;}
   }
}


/******************************************************************************************************************************
**函数名称:DisCurTime()                                                                                                     **
**函数功能:在指定位置显示实时芯片内的时间                                                                                   **   
**入口参数:显示位置x, y坐标                                                                                                 **
**出口参数:无                                                                                                               **
**具体资源:无                                                                                                               **
**调用程序:ReadPCF8583(), DisStr()                                                                                          **
**备    注:                                                                                                                 **
******************************************************************************************************************************/
void DisCurTime(unsigned char x, unsigned char y)
{
    unsigned char time[3];
	unsigned char dispBuff[9];
	ReadPCF8583(0x02, 3, time);
	dispBuff[8] = '\0';                                                 /* 在数组最后单元放入标识符以便判断内容结束         */
    dispBuff[7] = (time[0] & 0x0f) + '0';                               /* 提取秒个位                                       */
	dispBuff[6] = (time[0] >> 4)   + '0';                               /* 提取秒十位                                       */
	dispBuff[5] = ':';
	dispBuff[4] = (time[1] & 0x0f) + '0';	                            /* 提取分个位                                       */
	dispBuff[3] = (time[1] >> 4)   + '0';                               /* 提取分十位                                       */
	dispBuff[2] = ':';
	dispBuff[1] = (time[2] & 0x0f) + '0';	                            /* 提取时个位                                       */
	dispBuff[0] = ((time[2] >> 4) & 0x03) + '0';                        /* 提取时十位                                       */
	DispStr(y*20+x, dispBuff);
}

/******************************************************************************************************************************
**函数名称:显示日期                                                                                                         **
**函数功能:在指定位置显示实时芯片内的日期                                                                                   **   
**入口参数:显示位置x, y坐标                                                                                                 **
**出口参数:无                                                                                                               **
**具体资源:无                                                                                                               **
**调用程序:ReadPCF8583(), DisStr()                                                                                          **
**备    注:                                                                                                                 **
******************************************************************************************************************************/
void DisCurDate(unsigned char x, unsigned char y)
{
    unsigned char Date[2];
	unsigned char DisBuf[11];
	ReadPCF8583(0x05, 2, Date);                                         /* 获取PCF8583的日期                                */         
	DisBuf[4] = (Date[0] & 0x0f) + '0';	                                /* 提取日个位                                       */
	DisBuf[3] = ((Date[0] >> 4) & 0x03) + '0';                          /* 提取日十位                                       */
	DisBuf[2] = '/';
	DisBuf[1] = (Date[1] & 0x0f) + '0';	                                /* 提取月个位                                       */
	DisBuf[0] = ((Date[1] >> 4) & 0x01) + '0';                          /* 提取月十位                                       */
	DisBuf[5] = '/';
    DisBuf[6] = '2';
    DisBuf[7] = '0';
    DisBuf[8] = '0';
    DisBuf[9] = '8';
    DisBuf[10]= '\0';                                                   /* 在数组最后单元放入标识符以便判断内容结束         */
    DispStr(y*20+x, DisBuf);
}

/******************************************************************************************************************************
**函数名称:DisClock()                                                                                                       **
**函数功能:绘制钟面                                                                                                         **   
**入口参数:显示位置                                                                                                         **
**出口参数:无                                                                                                               **
**具体资源:无                                                                                                               **
**调用程序:Circle(), Line(), WriteEN(), EasyCH()                                                                            **
**备    注:                                                                                                                 **
******************************************************************************************************************************/
void DrawClock(unsigned char x, unsigned char y, unsigned char r)
{
    Circle(x, y, r);
    Line(x, y-r, x, y-r+5, 0);                                          /* 绘制0点处竖线                                    */
    Line(x, y+r, x, y+r-5, 0);                                          /* 绘制6点处竖线                                    */
    Line(x-r, y, x-r+5, y, 0);                                          /* 绘制9点处竖线                                    */
    Line(x+r, y, x+r-5, y, 0);                                          /* 绘制3点处竖线                                    */
    WriteEN(198,'E');
    WriteEN(273,'S');
    WriteEN(189,'W');
    WriteEN(93,'N');
    EasyCH(3, 1, fang);
    EasyCH(3, 2, wei);
}


/******************************************************************************************************************************
**函数名称:GraphicTest()                                                                                                    **
**函数功能:显示子函数测试程序                                                                                               **   
**入口参数:无                                                                                                               **
**出口参数:无                                                                                                               **
**具体资源:无                                                                                                               **
**调用程序:显示子函数                                                                                                       **
**备    注:                                                                                                                 **
******************************************************************************************************************************/
void GraphicTest(void)
{
  	Circle(80, 63, 60);
	Rectangle(0, 0, 159, 127, 0);
	Triangle(0, 0, 20, 30, 120, 50);
	Line(0, 0, 159, 127, 0);
	Line(0, 127, 159, 0, 1);
}

/******************************************************************************************************************************
**函数名称:DisMain()                                                                                                        **
**函数功能:主显示界面                                                                                                       **   
**入口参数:显示位置                                                                                                         **
**出口参数:无                                                                                                               **
**具体资源:无                                                                                                               **
**调用程序:无                                                                                                               **
**备    注:仅用作测试使用                                                                                                   **
******************************************************************************************************************************/
void DisMain(void)
{
    Rectangle(0, 22, 159, 127, 0);
    DrawClock(113, 70, 45);    
    Line(0, 115, 159, 115, 0);
    Line(64, 22, 64, 115, 0);
}


/******************************************************************************************************************************
**函数名称:DisCurDirc()                                                                                                     **
**函数功能:显示当前方位指针                                                                                                 **   
**入口参数:显示角度                                                                                                         **
**出口参数:无                                                                                                               **
**具体资源:无                                                                                                               **
**调用程序:WriteEN(), Line()                                                                                                **
**备    注:                                                                                                                 **
******************************************************************************************************************************/
void DisCurDirc(unsigned int Dir)
{
    unsigned char tempx, tempy;
    unsigned char Dir1, Dir2, Dir3;
    
    Dir1 = Dir/100 +'0';                                                /* 提取其各位                                       */
    Dir2 = (Dir%100)/10 + '0';
    Dir3 = (Dir%100)%10 + '0';
    WriteEN(122, Dir1);
    WriteEN(123, Dir2);
    WriteEN(124, Dir3);
    
    Dir = Dir/3;                                                        /* 不满3的倍数的按3的倍数算                         */
    tempx = DirTbl[(Dir<<1)];
    tempy = DirTbl[((Dir<<1)+1)];
    LineClr(113, 70, oldtempx, oldtempy);
    Line(113, 70, tempx, tempy, 0); 
    oldtempx = tempx;
    oldtempy = tempy;
}

/******************************************************************************************************************************
**函数名称:SendAngle()                                                                                                      **
**函数功能:向串口送当前角度值                                                                                               **   
**入口参数:当前角度                                                                                                         **
**出口参数:无                                                                                                               **
**具体资源:无                                                                                                               **
**调用程序:UartSendStr(), UartSendByte()                                                                                    **
**备    注:                                                                                                                 **
******************************************************************************************************************************/
void SendAngle(unsigned int Dir)
{
    unsigned char Dir1, Dir2, Dir3;    
    unsigned char Str[] = "Current angle = 360 degree !";

    Dir1 = Dir/100 +'0';                                                /* 提取其各位                                       */
    Dir2 = (Dir%100)/10 + '0';
    Dir3 = (Dir%100)%10 + '0'; 
    
    sprintf(Str, "Current angle = %c%c%c degree !", Dir1,Dir2,Dir3);
    UartSendStr(Str);
    UartSendByte(0x0d);
    UartSendByte(0x0a); 
}

/******************************************************************************************************************************
**函数名称:外部中断0 ISR                                                                                                    **
**函数功能:获取键值                                                                                                         **   
**入口参数:无                                                                                                               **
**出口参数:无                                                                                                               **
**具体资源:无                                                                                                               **
**调用程序:无                                                                                                               **
**备    注:                                                                                                                 **
******************************************************************************************************************************/
INT0IRQ (void) interrupt 0
{
    unsigned char keytmp;
    EA = 0;
    delay(10);
    keytmp = (P1 & 0xf8);                                               /* 保留高5位                                        */
    if (keytmp == 0xf8) {                                               /* 抖动                                             */
    EA = 1;
    }else {
        switch (keytmp) {                                               /* Key1                                             */
            case 0x78 : 
                keyflag = 1;
                break;                                                  /* Key2                                             */
            case 0xb8 : break;                                          /* Key3                                             */
            case 0xd8 : break;                                          /* Key4                                             */
            case 0xe8 : break;                                          /* Key5                                             */
            case 0xf0 : break;
            default : break;
        }
    EA = 1;
    }
}



/******************************************************************************************************************************
**函数名称:定时器0 ISR                                                                                                      **
**函数功能:定时器0中断服务程序                                                                                              **   
**入口参数:无                                                                                                               **
**出口参数:无                                                                                                               **
**具体资源:无                                                                                                               **
**调用程序:无                                                                                                               **
**备    注:                                                                                                                 **
******************************************************************************************************************************/
T0IRQ (void) interrupt 1
{
    EA  = 0;
    TR0 = 0;
    T0IRQCNT++;
    TR0 = 1;
    EA  = 1;
}


/******************************************************************************************************************************
**函数名称:GetAngle()                                                                                                       **
**函数功能:获取方向角度                                                                                                     **   
**入口参数:无                                                                                                               **
**出口参数:无                                                                                                               **
**具体资源:无                                                                                                               **
**调用程序:无                                                                                                               **
**备    注:                                                                                                                 **
******************************************************************************************************************************/
void GetAngle(void)
{
    unsigned char Dir1, Dir2, Dir3;    
                                    
    Dir1 = COMBUF[0] - '0';
    if (Dir1 > 3) {
        
    }else {
        Dir2 = COMBUF[1] - '0';
        Dir3 = COMBUF[2] - '0'; 
        Angle = Dir1 * 100 + Dir2 * 10 + Dir3;
    }
}


/******************************************************************************************************************************
**函数名称:主测试函数                                                                                                       **
**函数功能:                                                                                                                 **   
**入口参数:无                                                                                                               **
**出口参数:无                                                                                                               **
**具体资源:无                                                                                                               **
**调用程序:无                                                                                                               **
**备    注:                                                                                                                 **
******************************************************************************************************************************/

void main(void)
{
    InitScreen();
    
    InitCOM();
    DisMain();
    EX0 = 1;                                                            /* 外部中断0开                                      */
    IT0 = 1;                                                            /* 外部中断0为边沿触发                              */

    DisCurDate(0, 15);                                                  /* 显示系统日期                                     */
    Angle = 1;
    while(1)
	{
        GetAngle();
        if (T0IRQCNT == 5) {
            DisCurDirc(Angle);
        }
        DisCurTime(11, 15);                                             /* 显示系统时间                                     */	                       
        switch (keyflag) {
            case 1 : 
                SendAngle(Angle);
                keyflag = 0;
                break;
            default : break;
        }                                               
    }
}

完整资料:

https://market.m.taobao.com/app/idleFish-F2e/widle-taobao-rax/page-detail?wh_weex=true&wx_navbar_transparent=true&id=614513242483&ut_sk=1.WUpxx7gpwUoDAMmnnrBIzAno_12431167_1585228024499.Copy.detail.614513242483.1828622527&forceFlush=1

发布了23 篇原创文章 · 获赞 7 · 访问量 320

猜你喜欢

转载自blog.csdn.net/weixin_41017942/article/details/105128616
今日推荐