一板网电子技术论坛

风筝
发表于: 2018-10-4 09:35:12 | 显示全部楼层

本篇文章主要描述了如何通过I2C总线连接一个简单的GPS模块。使用的控制器是ATtiny841:

i2cgps.jpg


简介

将GPS纳入到项目中是一项非常艰巨的任务。首先,您必须正确解析您使用的GPS模块返回的NMEA语句,然后如果您使用接收到的经度和纬度进行任何计算,则需要将浮点GPS库结合到例程中来执行计算。


如果您需要处理一些任何其他重要的事情,GPS处理任务可能会干扰您的其他任务。将GPS处理作为单独的I2C模块解决了这个问题。


我最初设计这个是为运行我的Lisp解释器uLisp的电路板提供GPS支持,但它对于您希望通过简单的I2C接口访问GPS数据的任何其他应用程序都很有用。


GPS变量

I2C数据中的18个字节包含从NMEA消息中提取的原始GPS数据:

i2cgpscodes.gif


这些变量如下:

偏移量
变量
说明
0
Time
以HH:MM格式表示的时间。
2
Csecs
以厘秒为单位的秒数。
4
Lat
以1e-4弧分为单位的纬度。
8
Long
以1e-4弧分为单位的经度。
12
Knots
速度,单位1e-2节。
14
Course
轨道,单位1e-2度。
16
Date
DD:MM格式的日期。

角度测量、纬度和经度以1e-4弧分为单位返回。因此,一度表示为600,000单位。这旨在允许使用长整数来完成算术,并且非常适合解析GPS模块返回的值而不会丢失任何精度。

◾    如果您喜欢使用百万分之一度的纬度和经度,就像其他一些GPS库一样,只需乘以5/3即可。

◾    如果要将纬度和经度用作浮点数(以度为单位),请将它们除以6e5。

◾    如果您想使用纬度和经度作为度、弧分和弧秒,请使用下面演示程序中的计算。


电路

我决定将电路基于ATtiny841控制器,因为它在硬件中提供USART和从I2C功能:

i2cgpsmodule.gif


为方便起见,我使用了Adafruit Ultimate GPS Breakout,但该电路适用于其他GPS模块。


由于ATtiny841仅采用SOIC封装,我将其安装在分线板上。 GPS模块和分线板都整齐地安装在迷你面包板上,可从SparkFun获得。


我使用了一个晶振时钟,虽然您可以使用内部8MHz振荡器,只要您使用OSCCAL寄存器进行校准即可。我在晶体和Vcc之间连接了18pF电容,而不是传统的GND,以使原型板上的布线更容易。这不应该影响电路的运行。


根据您连接I2C GPS模块的情况,您可能需要在SDA和SCL线路与Vcc之间使用4.7kΩ上拉电阻。我发现我将模块连接到Arduino Uno时不需要他们,但使用Aduino Zero则确实需要他们。


程序代码

首先,我们定义一个typedef,它定义了一个18字节的buffer_t类型,也可以通过GPS变量名称或字节数组来引用:

  1. // GPS variables
  2. typedef union {
  3.   struct {
  4.     unsigned int Time, Csecs;
  5.     long Lat, Long;
  6.     unsigned int Knots, Course, Date;
  7.   };
  8.   uint8_t Data[buffersize];
  9. } buffer_t;
复制代码

该程序的工作原理如下。当从GPS模块接收到每个字符时,由ParseGPS()函数解析,该函数将GPS变量写入gps.Data []缓冲区,直到Fix指示已收到完整的NMEA句子:

  1.   do {
  2.     while (!Serial.available());
  3.     char c = Serial.read();
  4.     ParseGPS(c);
  5.   } while(!Fix);
复制代码

I2C接口产生TWI中断,对于通过I2C接口写入或读取的每个字节调用TWI_SLAVE中断。 I2C接口直接从gps.Data []缓冲区读取数据是不安全的。想象一下,当我们在中断时通过I2S访问缓冲区时,是否从GPS模块读取GPS数据。当我们读取LSB时,双字节时间可能是11:59。但是,当我们读取MSB时,它可能已更改为12:00。然后我们将以12:59的时间结束,这将是完全错误的。任何其他字段都可能出现同样的问题。


为防止这种情况,我们使用两个缓冲GPS数据由ParseGPS()写入gps.Data [],当我们收到完整的NMEA消息时,会在一次操作中将其复制到buf.Data [],并禁用中断。


如果我们通过I2C直接从buf.Data []读取,可能会发生同样的问题。在读取两个连续字节之间可以更新数据。解决方案是在I2C例程开始时将buf.Data []复制到第三个缓冲区i2c.Data []。然后我们从这个安全数据中读取数据,直到它是一致的。


另一种解决方案是让一个过程等到另一个过程完成。但是,使用单独的缓冲区是一种更优雅的解决方案,可确保数据始终保持一致而不会占用程序。


该电路提供可选的INT输出,当接收到完整的NMEA语句以指示新数据准备好时,该输出为低电平。当I2C读取数据时,输出再次变为高电平。


TWI中断服务程序

我决定自己实现从属软件,而不是使用库,目的是使项目尽可能简单。以下处理I2C接口的代码:

  1. ISR(TWI_SLAVE_vect) {
  2.   if (TWSSRA & 1<<TWASIF) {                // Address received
  3.     if (TWSSRA & 1<<TWDIR) {               // Master read
  4.       // Copy buf buffer to i2c buffer so it's ready to be read
  5.       for (int i=0; i<buffersize; i++) i2c.Data[i] = buf.Data[i];
  6.       // Take INT pin high
  7.       digitalWrite(Interrupt, HIGH);
  8.       TWSCRB = 3<<TWCMD0;                  // ACK
  9.     } else {                               // Master write
  10.       TWSCRB = 3<<TWCMD0;                  // ACK
  11.     }
  12.   } else if (TWSSRA & 1<<TWDIF) {          // Data interrupt
  13.     if (TWSSRA & 1<<TWDIR) {               // Master read
  14.       if (Position >= 0 && Position < buffersize) {
  15.         TWSD = i2c.Data[Position++];
  16.         TWSCRB = 3<<TWCMD0;
  17.       } else {
  18.         TWSCRB = 2<<TWCMD0;                // NAK and complete
  19.       }
  20.     } else {                               // Master write
  21.       Position = TWSD;                     // Write sets position
  22.       TWSCRB = 3<<TWCMD0;                  // ACK
  23.     }
  24.   }
  25. }
复制代码

这个例程的逻辑如下:

◾    如果中断是针对地址的:

      ◾    如果是一次读取:复制将由i2c读取的GPS数据,以及ACK

      ◾    如果是一次写入:只是ACK。

◾    如果中断是针对数据的:

      ◾    如果是一次读取:从位置的缓冲区读取数据。

      ◾    如果是一次写入:将缓冲区指针Position设置为byte。


每个I2C会话都以写入开始,以指定缓冲区中的偏移量以读取后续变量。然后,您可以读取任意数量的字节以获取要访问的变量。


编译程序

我使用Spence Konde的新ATTiny Core编译了该程序,该核心现在支持所有ATtiny处理器并取代了早期的各种ATtiny内核。在Boards菜单上的ATtiny Universal标题下选择ATtinyx41选项。然后后续菜单选择B.O.D. Disabled, ATtiny841, 8 MHz (external)


通过合适的编程器将电路连接到计算机,例如Tiny AVR Programmer Board,然后从Programmer菜单中选择编程器。请注意,您必须选择标记为(ATtiny)的编程器才能正确上传到大多数支持的芯片 - 这显然是由于IDE的限制。


选择Burn Bootloader以适当设置保险丝。然后选择Upload将程序上传到ATtiny841。


这是整个I2C GPS模块程序: I2C GPS模块程序.rar (1.72 KB, 下载次数: 0)

跳转到指定楼层
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题 15 | 回复: 21



Archiver|手机版|小黑屋|

GMT+8, 2018-10-16 23:00 , Processed in 0.046874 second(s), 32 queries . Powered by Discuz! X3.4

YiBoard一板网 © 2015-2018 地址:河北省石家庄市长安区高营大街 ( 冀ICP备18020117号 )

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