查看: 637|回复: 0
打印 上一主题 下一主题

使用PNI方案的指南针制作成功,奉献所有资料

[复制链接]
跳转到指定楼层
沙发
发表于 2016-4-13 20:13:52 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
先上图

ZNZ_PNI11096,NOKIA5110 (原文件名:ZNZ_1.jpg)
第一行是X轴数据,第二行是Y轴数据,第三行是计算出来的角度


ZNZ_PNI11096 (原文件名:ZNZ_2.jpg)
将 PNI11096 和 X、Y轴的传感器 制成的一个小模块


PNI11096 和 X、Y轴的传感器 制成的模块PCB图

PNI11096 和 X、Y轴的传感器 制成的一个小模块 (原文件名NI11096.jpg)

原理图就是PNI11096数据手册上的


PNI11096数据手册ourdev_574610.rar(文件大小:861K) (原文件名NI11096文档.rar)



没有源码就不是奉献所有资料了:

PNI11096的驱动函数:


/*
PNI11096的驱动函数
作者:XGGZ_WB   王波
2010年8月3日
*/

#define PNI_DDR   DDRC
#define PNI_PORT  PORTC
#define PNI_PIN   PINC

#define PNI_SSNOT        5
#define PNI_RESET         1
#define PNI_DRDY        0
#define PNI_MOSI         4
#define PNI_MISO         3
#define PNI_SCLK         2

//输出端口
#define PNI_SSNOT_1         PNI_PORT|=1<<NI_SSNOT
#define PNI_SSNOT_0         PNI_PORT&=~(1<<NI_SSNOT)

#define PNI_RESET_1         PNI_PORT|=1<<NI_RESET
#define PNI_RESET_0         PNI_PORT&=~(1<<NI_RESET)

#define PNI_MOSI_1         PNI_PORT|=1<<NI_MOSI
#define PNI_MOSI_0         PNI_PORT&=~(1<<NI_MOSI)

#define PNI_SCLK_1         PNI_PORT|=1<<NI_SCLK
#define PNI_SCLK_0         PNI_PORT&=~(1<<NI_SCLK)

//输入端口
#define PNI_READ_DATA         (PNI_PIN&(1<<NI_MISO))
#define PNI_READ_READY         (PNI_PIN&(1<<NI_DRDY))//这对括号让我多花了三天的时间,差点崩溃了

void PNI_PORT_INIT(void)
{
  PNI_DDR |= (1<<PNI_SSNOT)|(1<<PNI_RESET)|(1<<PNI_MOSI)|(1<<PNI_SCLK);
  PNI_DDR &= ~((1<<PNI_MISO)|(1<<PNI_DRDY));
  PNI_PORT|= (1<<PNI_MISO)|(1<<PNI_DRDY);
   
PNI_SSNOT_1;
PNI_RESET_0;
PNI_SCLK_0;
PNI_MOSI_0;
}
void PNI_INIT(void)
{
PNI_SSNOT_1;
PNI_RESET_0;
PNI_SCLK_0;
}

int PNI_READ(unsigned char command)
{
char i;
int data=0;
PNI_SCLK_0;         
PNI_SSNOT_0;         
_delay_us(5);
PNI_RESET_1;      
_delay_us(5);
PNI_RESET_0;
_delay_us(5);
   
   for(i=0;i<8;i++)
   {
     if(command&(1<<(7-i))){PNI_MOSI_1;}else{PNI_MOSI_0;}
     _delay_us(2);
     PNI_SCLK_1;     
     _delay_us(2);
     PNI_SCLK_0;
   }
        
   while(!PNI_READ_READY);

   for(i=0; i<=15; i++)         
   {
         _delay_us(2);
         if(PNI_READ_DATA){data|=1<<(15-i);}
         PNI_SCLK_1;
         _delay_us(2);
     PNI_SCLK_0;
   }
PNI_SSNOT_1;        
return data;
}
//


主文件:
#include <avr/io.h>
#include <util/delay.h>
#include "PNI.H"
#include <math.h>
#include "lcd5110.h"

void delay_nms(unsigned int n)
{
while(n--){_delay_ms(1);}
}
//
unsigned int GET_ANGLE(float x,float y)//计算方位角
{
        
        unsigned int angle=0;
        angle=fabs(atan(y/x)*180/M_PI);//可以不取绝对值,在各象限时的计算全部必为 “+angle”
        
if(x>=0 && y>=0)//第一象限
        {
         return angle;
        }
else if(x<0 && y>=0)//第二象限
        {
         return 180-angle;
        }
else if(x<0 && y<0)//第三象限
        {
         return 180+angle;
        }
else if(x>=0 && y<0)//第四象限
        {
         return 360-angle;
        }
return 999;
        
}

int main(void)
{
DDRA=0X00;
PORTA=0X00;

DDRB=0XFF;
PORTB=0X00;

DDRC=0XFF;
PORTC=0X00;

DDRD=0XFF;
PORTD=0X00;

DDRA=0xFF;
PORTA=0x3F;

LCD_init();
LCD_clear();

PNI_PORT_INIT();
PNI_INIT();//可以不要

float x=0,y=0;
while(1){
x=1;
y=1;

x=PNI_READ(0X41);delay_nms(5);
y=PNI_READ(0X42);//delay_nms(30);


LCD_write_english_string(0,0,"PNI_X=");LCD_write_ulong(6*6,0,x);
LCD_write_english_string(0,1,"PNI_Y=");LCD_write_ulong(6*6,1,y);

LCD_write_english_string(0,2,"ANGLE=");LCD_write_ulong(6*6,2,GET_ANGLE(x,y));

delay_nms(100);

}

}


程序只是简单的计算出方位角,没有做任何修正计算,如果要进行修正计算,可以看上面的几篇文档。


最后发表一下制作感想:

    在本坛搜索一下指南针,可以找到几种方案,但使用PNI方案的的还没有,至少没有人发布成功的案例。我在网上搜索PNI11096,可以搜索到许多信息,但还没有能够方便得到具体制作方案和源代码的。也找到许多相关PNI11096的论文,发现没有一个是有用的,多数论文是在原数据手册上抄几句,搞几个截图,再说几句海阔天空的话。想从里面找到问题的答案,简直是不可能的。找得我恢必丧气,最后还是自己摸索,硬着头皮看英文说明,用时间和汗水搞出来了。回过头来一看,其实也不是那么复杂嘛。

    此方案的模块有几个地方有,一个是富安达,一个是天祥电子,但他们都是只买模块,不提供代码的。

    还没做出来时,我想,既然翻遍了都找不到示例代码,有买模块的,但又不提供代码,那说明这个东西还挺难的,我做出来了说不定也可以赚点money,于是鼓足干劲,搞了5天,最后做出来之后,发现是一个括号耽误了我三天。

    想来想去,还是开源吧,反正又不是什么高深的东西。

    我从这里找到了很多我想要的东西,这个东西如果你想要就拿去吧。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入因仑

本版积分规则

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