先上图
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天,最后做出来之后,发现是一个括号耽误了我三天。
想来想去,还是开源吧,反正又不是什么高深的东西。
我从这里找到了很多我想要的东西,这个东西如果你想要就拿去吧。
|