/*********************************************************************************/
#include <avr/io.h>
#include <avr/signal.h>
#include <avr/interrupt.h>
//#include "lcd1602.h"
/**********函数声明*********************/
void INT_INIT();
void init_USART( );
/**************变量定义*****************/
//转换用到的变量
unsigned char speeds;
unsigned char speed_bai;
unsigned char speed_shi;
unsigned char speed_ge;
unsigned char speed_dh;
//GPS数据存储数组
unsigned char JD[10]; //经度
unsigned char JD_a; //经度方向
unsigned char WD[9]; //纬度
unsigned char WD_a; //纬度方向
unsigned char time[6]; //时间
unsigned char speed[5]; //速度
unsigned char high[6]; //高度
unsigned char angle[5]; //方位角
unsigned char use_sat[2]; //使用的卫星数
unsigned char total_sat[2]; //天空中总卫星数
unsigned char lock; //定位状态
//串口中断需要的变量
unsigned char seg_count; //逗号计数器
unsigned char dot_count; //小数点计数器
unsigned char byte_count; //位数计数器
unsigned char cmd_number; //命令类型
unsigned char mode; //0:结束模式,1:命令模式,2:数据模式
unsigned char buf_full; //1:整句接收完成,相应数据有效。0:缓存数据无效。
unsigned char cmd[5]; //命令类型存储数组
/*----------------------外部中断--------------------------------*/
void INT_INIT(void)
{
MCUCR=0x02; //注意该寄存器有多个功能
/*
ISCx1:0=00 INTx引脚为低电平时产生中断请求
ISCx1:0=01 INTx引脚上任意的逻辑电平变化都将引发中断
ISCx1:0=10 INTx引脚的下降沿产生中断请求
ISCx1:0=11 INTx引脚的上升沿产生中断请求
*/
/*
ISC2=0 INT2引脚的下降沿产生异步中断请求
ISC2=1 INT2引脚的上升沿产生异步中断请求
*/
GIFR=0x40;//写1清除标志位,在使能中断前最好先把对应
// 的标志位清除,以免误触发
GICR=(1<<INT0); //使能三个外部中断
//
}
/*----------------------延时函数--------------------------------*/
void delay_ms ( uint16_t i )
{
uint16_t j ;
while ( i-- )
{
j=1000 ;
while ( j-- ) ;
}
}
/*--------------------串口程序------------------------*/
void put_c(unsigned char c) //发送采用查询方式
{
while( !(UCSRA & (1<<UDRE)) );
UDR=c;
}
void put_s(unsigned char *ptr)
{
while (*ptr)
{
put_c(*ptr++);
}
put_c(0x0D);
put_c(0x0A); //结尾发送回车换行
}
void init_USART(void)//USART 初始化
{
//USART 9600 8, n,1 PC上位机软件(超级终端等)也要设成同样的设置才能通讯
UCSRC = (1<<URSEL) | 0x06;
//异步,8位数据,无奇偶校验,一个停止位,无倍速
/*
UBRRH与UCSRC共用I/O 地址。因此访问该地址时需注意以下问题。
写访问
当在该地址执行写访问时, USART 寄存器选择位(URSEL)控制被写入的寄存器。
若URSEL为0,对UBRRH值更新;若URSEL为1,对UCSRC设置更新
读访问
对UBRRH 或UCSRC 寄存器的读访问则较为复杂。但在大多数应用中,基本不需要读这些寄存器
没有UBRR这个16位寄存器,因为UBRRL(0x09)/UBRRH(0x20)的地址不连续,而且UBRRH跟UCSRC共用地址
*/
//U2X=0时的公式计算
UCSRA = 0x00;
UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN);
UBRRL= 95;
UBRRH= 0;
//U2X=1时的公式计算
// UBRRL= (F_CPU/BAUDRATE/8-1)%256;
// UBRRH= (F_CPU/BAUDRATE/8-1)/256;
//也可根据数据手册的[波特率设置的例子]查得
//UBRRL = 0x2F; //set baud rate lo
//UBRRH = 0x00; //set baud rate hi
// UCSRA = 0x00;
// UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN);
//使能接收中断,使能接收,使能发送
}
//#pragma interrupt_handler uart0_rx_isr:12
//void uart0_rx_isr(void)
SIGNAL(SIG_USART_RECV) //串口接收中断服务程序
{
unsigned char tmp;
//uart has received a character in UDR
tmp=UDR;
switch(tmp)
{
case '$':
cmd_number=0; //命令类型清空
mode=1; //接收命令模式
byte_count=0; //接收位数清空
break;
case ',':
seg_count=seg_count+1; //逗号计数加1
byte_count=0;
break;
case '*':
switch(cmd_number)
{
case 1:
buf_full|=0x01;
break;
case 2:
buf_full|=0x02;
break;
case 3:
buf_full|=0x04;
break;
}
mode=0;
break;
default:
if(mode==1){
//命令种类判断
cmd[byte_count]=tmp; //接收字符放入类型缓存
if(byte_count>=4){ //如果类型数据接收完毕,判断类型
if(cmd[0]=='G'){
if(cmd[1]=='P'){
if(cmd[2]=='G'){
if(cmd[3]=='G'){
if(cmd[4]=='A'){
cmd_number=1;
mode=2;
seg_count=0;
byte_count=0;
}
}
else if(cmd[3]=='S'){
if(cmd[4]=='V'){
cmd_number=2;
mode=2;
seg_count=0;
byte_count=0;
}
}
}
else if(cmd[2]=='R'){
if(cmd[3]=='M'){
if(cmd[4]=='C'){
cmd_number=3;
mode=2;
seg_count=0;
byte_count=0;
}
}
}
}
}
}
}
else if(mode==2){
//接收数据处理
switch (cmd_number){
case 1: //类型1数据接收。GPGGA
// $GPGGA,161229.487,3723.2475,N,12158.3416,W,1,07,1.0,9.0,M, , , ,0000*18
switch(seg_count){
case 2: //纬度处理