/****************************************************************************** 版权所有: 文件名称: rt_gps.c 文件版本: 01.01 创建作者: sunxi 创建日期: 2008-06-04 功能说明: GPS时钟模块驱动程序。 其它说明: 1. GPS卫星同步时钟只保证整秒时PR上升沿的精度(一般1us之内), 其它bit的上升沿精度并不保证。 2. GPS接收模块只给出秒脉冲和串口数据。 3. 使用B码对时的时候,B码给的数据中可能包含闰秒(负闰秒:58->0; 正闰秒:60->0),所以秒的有效数据范围为0~60。但是系统中其它 计时模块没有闰秒的概念,单独在B码模块使用闰秒有可能造成整个计时 系统的混乱,所以最终决定将秒的有效数据范围还是限制在0~59,这样 当正闰秒出现时,系统时间将是:58->59->0->0-1。初步估计,这种影响 在可接受的范围之内。 4. 目前在冷火Linux平台上对时误差<8US.(2010-11-23) 修改记录: */ /*------------------------------- 头文件 -------------------------------------- */ #include "bspconfig.h" #include "my_rtc.h" #include "rt.h" #include "bsp_ccu.h" #include "bsp_ustimer.h" #include "rt_printf.h" #include "rt_types.h" #include #include "gps.h" #include #include #include #include /*------------------------------- 宏定义 -------------------------------------- */ #if CFG_BSP_DEBUG #define _DEBUG_GPS #endif #define DTIM_CLOCK_PER_US (CFG_CPU_CLK / 2 / 1000000) #define GPS_SIGAL_DIFF 1 // GPS信号宽度误差 #define GPS_IRIG_CODE_0 0 #define GPS_IRIG_CODE_1 1 #define GPS_IRIG_CODE_P 2 /*------------------------------ 全局变量 ------------------------------------- */ extern int g_clock_mode; struct timespec g_sys_time; static struct rtc_time_t tmp_sys_time; // 毫秒中断的参考值 unsigned int g_1s_refence; // 输入信号是否合法,合法为1,不合法为0 int g_signal_valid; // GPS对时使用的保活计数值 unsigned int g_keep_alive_gps; // 处理B码的全局变量 unsigned int g_irig_old_value; unsigned int g_irig_old_interval; unsigned int g_irig_code_index; unsigned char g_irig_code[100]; int g_gps_fd = -1; unsigned g_gps_mapped_size; void *g_gps_map_base, *g_gps_virt_addr; static void *gpio_base = NULL; /*------------------------------ 函数声明 ------------------------------------- */ int _gps_irig_decode(unsigned char *code, struct rtc_time_t *p_tm); void _ms_update_time(void); void _gps_capture_isr(void); void _gps_1s_isr(void); void gps_isr(void); /*------------------------------ 外部函数 ------------------------------------- */ /****************************************************************************** 函数名称: gps_init 函数版本: 01.01 创建作者: ocean 创建日期: 2025-11-21 函数说明: gps初始化。 参数说明: 无 返回值: 成功返回0. 修改记录: */ int gps_init(void) { struct timespec ts; struct rtc_time_t ct; void *temp_ccu_base, *temp_virt_l_base, *temp_virt_h_base, *temp_virt_ctl_base, *temp_virt_irq_base; unsigned long read_result; off_t target; unsigned page_size, offset_in_page; unsigned width = 8 * sizeof(int); target = TIMER_BASE; // 获取页面大小 g_gps_mapped_size = page_size = sysconf(_SC_PAGESIZE); offset_in_page = (unsigned)target & (page_size - 1); if (offset_in_page + width > page_size) { /* This access spans pages. * Must map two pages to make it possible: */ g_gps_mapped_size *= 2; } g_gps_fd = open("/dev/mem", O_RDWR | O_SYNC); if (g_gps_fd < 0) { printf("open(/dev/mem) failed.\n"); return -1; } fflush(stdout); g_gps_map_base = mmap(NULL, g_gps_mapped_size, PROT_READ | PROT_WRITE, MAP_SHARED, g_gps_fd, target & ~(off_t)(page_size - 1)); if (g_gps_map_base == (void *)-1) { printf("NULL pointer!\n"); } else { printf("BSP gps map Successfull!\n"); } fflush(stdout); /* Get linux system current time */ // 此处精度还可以再提高,但是ioctl接口读取rtc时间后会有问题,暂时先这样了 clock_gettime(CLOCK_REALTIME, &ts); timespec_to_rtc(ts, &ct, 1); if (ct.hour >= 24 || ct.min >= 60 || ct.month > 12 || ct.day > 31 || ct.day == 0 || ct.month == 0) // 读取系统时钟错误 { /* Reset linux system time */ ct.year = 8; ct.month = 8; ct.day = 8; ct.hour = 8; ct.min = 8; rtc_to_timespec(&ct, &ts); rt_printf("gps read system date data error!!!"); } g_sys_time.tv_sec = ts.tv_sec; g_sys_time.tv_nsec = ts.tv_nsec; g_gps_virt_addr = (char *)g_gps_map_base + offset_in_page; // printf("g_gps_virt_addr: %p %p %x\n", g_gps_virt_addr, g_gps_map_base, offset_in_page); // Init timer ccu clock /* set TMR3 clock source to HOSC, 8 pre-division */ temp_ccu_base = g_ccu_map_base + 0x080C; read_result = *(volatile u_int32_t *)(temp_ccu_base); read_result &= ~(0x01 << 24); read_result |= (1 << 31) | 3; *(volatile u_int32_t *)(temp_ccu_base) = read_result; // Enable timer3 /* set timer intervalue */ temp_virt_l_base = (char *)g_gps_map_base + 0x84; temp_virt_h_base = (char *)g_gps_map_base + 0x8C; *(volatile u_int32_t *)(temp_virt_l_base) = (ts.tv_nsec == 0) ? 3000000 : ts.tv_nsec / 1000 * 3; *(volatile u_int32_t *)(temp_virt_h_base) = 0x0; /* set mode to auto reload */ temp_virt_ctl_base = (char *)g_gps_map_base + 0x80; read_result = *(volatile u_int32_t *)(temp_virt_ctl_base); read_result &= TIMER_CTL_PERIODIC; *(volatile u_int32_t *)(temp_virt_ctl_base) = (read_result | TIMER_CTL_AUTORELOAD | TIMER_CTL_ENABLE); /* Enable timer interrupt */ temp_virt_irq_base = (char *)g_gps_map_base + 0x00; read_result = *(volatile u_int32_t *)(temp_virt_irq_base); *(volatile u_int32_t *)(temp_virt_irq_base) = (read_result | TIMER_IRQ_EN(3)); usleep(1); read_result = *(volatile u_int32_t *)temp_virt_ctl_base; read_result &= ~TIMER_CTL_ENABLE; *(volatile u_int32_t *)temp_virt_ctl_base = read_result; *(volatile u_int32_t *)(temp_virt_l_base) = 3000000; read_result |= (TIMER_CTL_ENABLE); *(volatile u_int32_t *)temp_virt_ctl_base = read_result; init_timer_1ms_thread(); return 0; } int timer_1ms(void *arg) { cpu_set_t set; CPU_ZERO(&set); CPU_SET(3, &set); pid_t tid = syscall(SYS_gettid); sched_setaffinity(tid, sizeof(cpu_set_t), &set); printf("Thread created successfully: %s, PID: %d LWP: %d\r\n", "timer_1ms", (int)syscall(SYS_gettid), (int)syscall(SYS_gettid)); prctl(PR_SET_NAME, "gps_check_isr_thread"); while (1) { gps_isr(); usleep(500); // 扫描间隔改为500us EWen } return 0; } void init_timer_1ms_thread(void) { // 设置实时性 pthread_attr_t attr; struct sched_param param; pthread_t thread; if (pthread_attr_init(&attr) != 0) { perror("pthread_attr_init failed"); return; } if (pthread_attr_setschedpolicy(&attr, SCHED_FIFO) != 0) { perror("pthread_attr_setschedpolicy failed"); goto cleanup; } param.sched_priority = 99; if (pthread_attr_setschedparam(&attr, ¶m) != 0) { perror("pthread_attr_setschedparam failed"); goto cleanup; } if (pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED) != 0) { perror("pthread_attr_setinheritsched failed"); goto cleanup; } if (pthread_create(&thread, &attr, timer_1ms, NULL) != 0) { perror("pthread_create failed"); goto cleanup; } // 分离线程 pthread_detach(thread); printf("PPS线程已启动并在后台运行\n"); cleanup: pthread_attr_destroy(&attr); } int gps_exit(void) { unsigned long read_result; void *temp_virt_ctl_base; if (g_gps_fd >= 0) { close(g_gps_fd); g_gps_fd = -1; } temp_virt_ctl_base = (char *)g_gps_map_base + 0x80; read_result = *(volatile u_int32_t *)(temp_virt_ctl_base); read_result &= ~(TIMER_CTL_ENABLE); *(volatile u_int32_t *)(temp_virt_ctl_base) = (read_result); if (munmap(g_gps_map_base, g_gps_mapped_size) == -1) { printf("munmap failed!"); return -1; } return 0; } int gps_get_time(struct timespec *p_ts) { unsigned long flags; register long tv_sec, tv_nsec; unsigned long read_result; void *temp_virt_cvl_base, *temp_virt_irq_base; // 检查参数 if (p_ts == 0) return -1; // 关中断 rt_irq_save(flags); tv_sec = g_sys_time.tv_sec; temp_virt_cvl_base = (char *)g_gps_map_base + 0x88; temp_virt_irq_base = (char *)g_gps_map_base + 0x04; // read_result = *(volatile u_int32_t*)(temp_virt_cvl_base); tv_nsec = 3000000 - (*(volatile u_int32_t *)(temp_virt_cvl_base)); if (((*(volatile u_int32_t *)(temp_virt_irq_base)) & (1 << 3)) != 0) { tv_sec += 1; tv_nsec = 3000000 - (*(volatile u_int32_t *)(temp_virt_cvl_base)); } // 恢复中断级别 rt_irq_restore(flags); p_ts->tv_sec = tv_sec; p_ts->tv_nsec = (tv_nsec / 3) * 1000; return 0; } int gps_set_time(struct timespec *p_ts) { int ret = 0; bool write_rtc = false; struct timespec r_ts; struct rtc_time_t rtc_set, rtc_read; unsigned int flags; unsigned int tmp; unsigned int read_result; void *temp_virt_ivl_base, *temp_virt_ctrl_base; if (!p_ts) { return -1; } // 转换为rtc格式 if (timespec_to_rtc(*p_ts, &rtc_set, 1) != 0) { return -11; } if (rtc_set.ms > 59999) { return -2; } if (rtc_set.min > 59) { return -3; } if (rtc_set.hour >= 24) { return -4; } if (rtc_set.day > 31) { return -5; } if (rtc_set.month > 12) { return -6; } rt_irq_save(flags); g_sys_time.tv_nsec = p_ts->tv_nsec; g_sys_time.tv_sec = p_ts->tv_sec; clk_time_get(&r_ts); timespec_to_rtc(r_ts, &rtc_read, 1); tmp = 3000000 - ((g_sys_time.tv_nsec / 1000) * 3); if (tmp > 3000000) tmp = 3000000; temp_virt_ctrl_base = (char *)g_gps_map_base + 0x80; temp_virt_ivl_base = (char *)g_gps_map_base + 0x84; read_result = *(volatile u_int32_t *)temp_virt_ctrl_base; read_result &= ~TIMER_CTL_ENABLE; *(volatile u_int32_t *)temp_virt_ctrl_base = read_result; // 暂停定时器后根据对时ms修改间隔寄存器的值然后开启定时器的同时reload计数寄存器从设置的ms开始跑 *(volatile u_int32_t *)(temp_virt_ivl_base) = tmp; read_result |= (TIMER_CTL_ENABLE | TIMER_CTL_AUTORELOAD); *(volatile u_int32_t *)temp_virt_ctrl_base = read_result; if (tmp != 3000000) { usleep(1); // 暂停定时器将间隔寄存器恢复3000000,即1s的定时器中断 read_result = *(volatile u_int32_t *)temp_virt_ctrl_base; read_result &= ~TIMER_CTL_ENABLE; *(volatile u_int32_t *)temp_virt_ctrl_base = read_result; *(volatile u_int32_t *)(temp_virt_ivl_base) = 3000000; read_result |= (TIMER_CTL_ENABLE); *(volatile u_int32_t *)temp_virt_ctrl_base = read_result; // ((TIMER_TypeDef *) g_timer_base)->TMR3_CVH_REG = 0x0; } rt_irq_restore(flags); // 更新RTC时间 write_rtc = false; // 秒脉冲修正不需要频繁写入rtc if (rtc_set.ms != rtc_read.ms) { if (rtc_set.ms >= rtc_read.ms) { if (rtc_set.ms - rtc_read.ms >= 10) { write_rtc = true; } } else { if (rtc_read.ms - rtc_set.ms >= 10) { write_rtc = true; } } } if (write_rtc) { ret = rtc_time_write(&rtc_set); if (ret == 0) { rt_err_clr(ERR_CODE_RTC, 0); } else { rt_printf("rtc_time_write:ret=%d.\r\n", ret); } } } /****************************************************************************** 函数名称: gps_disable 函数版本: 01.01 创建作者: 创建日期: 2014-12-02 函数说明: 禁止GPS输入功能。 参数说明: 无 返回值: 无. 修改记录: */ void gps_disable(void) { MCF_REG16(MCF_DTIM_DTMR(CFG_DTIM_GPS_CAP)) &= ~MCF_DTIM_DTMR_CE_ANY; } /****************************************************************************** 函数名称: gps_enable 函数版本: 01.01 创建作者: 创建日期: 2014-12-02 函数说明: 使能GPS输入功能。 参数说明: 无 返回值: 无. 修改记录: */ void gps_enable(void) { MCF_REG16(MCF_DTIM_DTMR(CFG_DTIM_GPS_CAP)) |= MCF_DTIM_DTMR_CE_ANY; } /****************************************************************************** 函数名称: gps_reset 函数版本: 01.01 创建作者: sunxi 创建日期: 2008-08-06 函数说明: gps对时模块复位。 参数说明: 无 返回值: 成功返回0. 修改记录: */ int gps_reset(void) { // 全局变量清零 g_signal_valid = 0; g_keep_alive_gps = 0; g_irig_old_value = 0; g_irig_old_interval = 0; g_irig_code_index = 0; return 0; } /****************************************************************************** 函数名称: gps_pulse_isr 函数版本: 01.01 创建作者: ocean 创建日期: 2023-11-24 函数说明: gps脉冲中断 参数说明: 无 返回值: 成功返回0. 修改记录: */ void gps_pulse_isr(void *data) { unsigned int flags; rt_irq_save(flags); g_sys_time.tv_sec++; rt_irq_restore(flags); } /****************************************************************************** 函数名称: gps_isr 函数版本: 01.01 创建作者: sunxi 创建日期: 2008-08-06 函数说明: gps中断处理函数。 参数说明: 无 返回值: 成功返回0. 修改记录: */ void gps_isr(void) { void *temp_virt_cvl_base, *temp_virt_irq_base; // clear irq flags if (g_gps_map_base) { temp_virt_irq_base = (char *)g_gps_map_base + 0x04; if (((*(volatile u_int32_t *)(temp_virt_irq_base)) & (1 << 3)) != 0) { gps_pulse_isr(NULL); *(volatile u_int32_t *)(temp_virt_irq_base) = (1 << 3); } } } /*------------------------------ 内部函数 ------------------------------------- */ // 闰年判断 int _is_leap_year(int year) { if ((((year & 0x3) == 0) && (year % 100 != 0)) || (year % 400 == 0)) return 1; else return 0; } // 日期转换,给出一年中的第几天(从1开始,不是从0开始),算出是这一年的几月几日 int _days_translate(struct rtc_time_t *pt, int year, int day) { static int month_last_day[2][13] = { {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}, // 平年 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}, // 闰年 }; int i; int *last_day; if (pt == 0 || day == 0 || day > 366) return -1; last_day = month_last_day[_is_leap_year(year)]; for (i = 0; i < 13; i++) { if (day <= last_day[i]) { break; } } pt->month = (unsigned char)i; pt->day = (unsigned char)(day - last_day[i - 1]); return 0; } int _gps_irig_decode(unsigned char *code, struct rtc_time_t *p_tm) { #if 0 int tmp; //检查P码位置 if( code[0]!=GPS_IRIG_CODE_P ||code[9]!=GPS_IRIG_CODE_P ||code[19]!=GPS_IRIG_CODE_P ||code[29]!=GPS_IRIG_CODE_P ||code[39]!=GPS_IRIG_CODE_P ||code[49]!=GPS_IRIG_CODE_P ||code[59]!=GPS_IRIG_CODE_P ||code[69]!=GPS_IRIG_CODE_P ||code[79]!=GPS_IRIG_CODE_P ||code[89]!=GPS_IRIG_CODE_P) return -1; //秒 tmp = ((code[8]<<2)+(code[7]<<1)+code[6])*10 +(code[4]<<3)+(code[3]<<2)+(code[2]<<1)+(code[1]); if(tmp>=60) return -2; p_tm->ms = (unsigned short)(tmp*1000 + p_tm->ms%1000); //分 tmp = ((code[17]<<2)+(code[16]<<1)+code[15])*10 +(code[13]<<3)+(code[12]<<2)+(code[11]<<1)+(code[10]<<0); if(tmp>=60) return -3; p_tm->min=(unsigned char)tmp; //时 tmp = ((code[26]<<1)+code[25])*10 +(code[23]<<3)+(code[22]<=24) return -4; p_tm->hour=(unsigned char)tmp; if(g_clock_mode == CLOCK_MODE_GPS_B_YEAR_NONE) { //不带年的B码对时 //日 tmp = ((code[41]<<1)+code[40])*100 +((code[38]<<3)+(code[37]<<2)+(code[36]<<1)+code[35])*10 + (code[33]<<3)+(code[32]<<2)+(code[31]<<1)+code[30]; if(tmp>366 || tmp == 0) return -5; p_tm->year = tmp_sys_time.year; _days_translate(p_tm,p_tm->year + 2000,tmp); } else if(g_clock_mode == CLOCK_MODE_GPS_B_YEAR) { //带年的B码对时 //日 tmp=((code[38]<<3)+(code[37]<<2)+(code[36]<<1)+code[35])*10+ (code[33]<<3)+(code[32]<<2)+(code[31]<<1)+code[30]; if(tmp>31||tmp==0) return -6; p_tm->day = (unsigned char)tmp; //月 tmp=(code[43]<<3)+(code[42]<<2)+(code[41]<<1)+code[40]; if(tmp > 12) return -7; p_tm->month = (unsigned char)tmp; //年 tmp=((code[58]<<3)+(code[57]<<2)+(code[56]<<1)+code[55])*10+ (code[53]<<3)+(code[52]<<2)+(code[51]<<1)+code[50]; p_tm->year = (unsigned short)tmp; } else if(g_clock_mode == CLOCK_MODE_GPS_B_2009) { //年 tmp=((code[58]<<3)+(code[57]<<2)+(code[56]<<1)+code[55])*10+ (code[53]<<3)+(code[52]<<2)+(code[51]<<1)+code[50]; p_tm->year = (unsigned short)tmp; //日 tmp = ((code[41]<<1)+code[40])*100 +((code[38]<<3)+(code[37]<<2)+(code[36]<<1)+code[35])*10 + (code[33]<<3)+(code[32]<<2)+(code[31]<<1)+code[30]; if(tmp>366 || tmp == 0) return -8; _days_translate(p_tm,p_tm->year + 2000,tmp); } #endif return 0; } void _ms_update_time(void) { struct rtc_time_t *pt = &tmp_sys_time; int day_flag = 0; if (pt->ms < 60000) return; pt->ms = 0; pt->min++; if (pt->min >= 60) { pt->min = 0; pt->hour++; if (pt->hour >= 24) { pt->hour = 0; pt->day++; if (pt->month == 2) { // 2月 if (pt->day > 28) { if (_is_leap_year(pt->year + 2000)) { // 闰年 2月29天? if (pt->day > 29) { day_flag = 1; } } else { // 其他28天 day_flag = 1; } } } else { // 非2月 if (pt->day > 30) { if (pt->month == 4 || pt->month == 6 || pt->month == 9 || pt->month == 11) { day_flag = 1; } } if (pt->day > 31) { day_flag = 1; } } if (day_flag) { pt->day = 1; pt->month++; if (pt->month > 12) { pt->month = 1; pt->year++; } } } } } void _gps_1s_isr(void) { // unsigned int now; // uint32_t flags; #if 0 if(tmp_sys_time.ms%2 == 0) { // DIO_KOUT6_OFF(); } else { // DIO_KOUT6_ON(); } //计数 tmp_sys_time.ms ++; //输出对时脉冲(10ms,下降沿) if((tmp_sys_time.ms%1000) >= 10 ) { //GPIO_GPS_HIGH(); } else if(tmp_sys_time.ms%1000 != 0) { //GPIO_GPS_LOW(); } else { //tmp_sys_time.ms%1000 == 0的情况 if(g_clock_mode == CLOCK_MODE_EXT || g_clock_mode == CLOCK_MODE_GPS_MINUTE) { //当对时模式为外部对时或分对时的时候,在这儿输出下降沿。 //GPIO_GPS_LOW(); } else if(g_signal_valid == 0) { //输入信号不合法,在此输出下降沿 //GPIO_GPS_LOW(); } } #endif rt_irq_save(flags); g_sys_time.tv_sec++; g_1s_refence += 1000000; MCF_REG32(MCF_DTIM_DTRR(CFG_DTIM_GPS_CAP)) = g_1s_refence; rt_irq_restore(flags); // 更新系统时间 //_ms_update_time(); // GPS保活处理 if (g_keep_alive_gps) { // 减1s g_keep_alive_gps -= 1000; } return; } void _gps_capture_isr(void) { #if 0 unsigned int interval,capture_value,n; //如果不是GPS对时模式,不进行任何处理 // if(g_clock_mode == CLOCK_MODE_EXT) return; //得到计数值,并计算和上一次计数器之差,也就是两次中断之间的计数值. capture_value = MCF_REG32(MCF_DTIM_DTCR(CFG_DTIM_GPS_CAP)); interval = (capture_value - g_irig_old_value + 500L)/1000; //消除干扰信号 if(interval < 2) { rt_printf("gps:interval = %d\r\n",interval); //干扰信号,直接返回 return; } #if 0 if(GPIO_GPS_INT_STATUS()) rt_printf("H:"); else rt_printf("L:"); rt_printf("%d,%d\r\n",capture_value - g_irig_old_value,capture_value); goto __ret; #endif if(g_clock_mode == CLOCK_MODE_GPS_SECOND) { //输入信号不为低电平时不进行逻辑判断。 //注意:目前输入信号经过了两个反相器。 if(GPIO_GPS_INT_STATUS() == 0) { goto __ret; } //检查输入信号正负脉冲之和是否为1000ms. n = interval + g_irig_old_interval; //if( n < 999 || n > 1001) if( abs(n - 1000) > GPS_SIGAL_DIFF) { //输入信号不正常,重新搜索秒开始位置 rt_printf("gps:%d,%d\r\n",interval,g_irig_old_interval); g_signal_valid = 0; goto __ret; } //分板对时下降沿 //GPIO_GPS_LOW(); //修正时间 tmp_sys_time.ms = (unsigned short)((tmp_sys_time.ms+500)/1000*1000); _ms_update_time(); //修正边沿 MCF_REG08(MCF_DTIM_DTER(CFG_DTIM_GPS_CAP)) = MCF_DTIM_DTER_REF; g_1s_refence = capture_value + 1000000; MCF_REG32(MCF_DTIM_DTRR(CFG_DTIM_GPS_CAP)) = g_1s_refence; //GPS保活 g_keep_alive_gps = CLOCK_ALIVE_GPS; g_signal_valid = 1; goto __ret; } if(g_clock_mode == CLOCK_MODE_GPS_MINUTE) { //输入信号不为低电平时不进行逻辑判断。 //注意:目前输入信号经过了两个反相器。 if(GPIO_GPS_INT_STATUS() == 0) { goto __ret; } //检查输入信号正负脉冲之和是否为1分钟。 //由于我们使用的晶体是50ppm的,在一分钟之内可能有3ms的误差, //所以我们以5ms作为指标判断。 n = interval + g_irig_old_interval; if( n < (60*1000 - 5) || n > (60*1000 + 5)) { //输入信号不正常,重新搜索分开始位置 rt_printf("gps:%d,%d\r\n",interval,g_irig_old_interval); g_signal_valid = 0; goto __ret;; } //分板对时下降沿 //GPIO_GPS_LOW(); //修正时间 if(tmp_sys_time.ms > 30000) { tmp_sys_time.ms = 60000; _ms_update_time(); } else { tmp_sys_time.ms = 0; } //修正边沿 MCF_REG08(MCF_DTIM_DTER(CFG_DTIM_GPS_CAP)) = MCF_DTIM_DTER_REF; g_1s_refence = capture_value + 1000000; MCF_REG32(MCF_DTIM_DTRR(CFG_DTIM_GPS_CAP)) = g_1s_refence; //GPS保活 g_keep_alive_gps = CLOCK_ALIVE_GPS + 60000; g_signal_valid = 1; goto __ret; } //!!!以下为B码对时 //检查输入信号 if(abs(interval - 2)> GPS_SIGAL_DIFF && abs(interval - 5) > GPS_SIGAL_DIFF && abs(interval - 8) > GPS_SIGAL_DIFF) { rt_printf("gps:%d\r\n",interval); //输入信号不正常,重新搜索秒开始位置 g_signal_valid = 0; g_irig_code_index = 0; goto __ret; } //输入信号不为低电平时不进行逻辑判断。 //注意:目前输入信号经过了两个反相器。 if(GPIO_GPS_INT_STATUS() == 0) { goto __ret; } //检查输入信号正负脉冲之和是否为10ms。 if(abs(interval + g_irig_old_interval - 10) > GPS_SIGAL_DIFF) { //输入信号不正常,重新搜索秒开始位置 rt_printf("gps:%d,%d\r\n",interval,g_irig_old_interval); g_signal_valid = 0; g_irig_code_index = 0; goto __ret;; } //如果g_irig_code_index<2,需要搜索秒开始位置 if(g_irig_code_index <2) { //如果不是P码,放弃处理,重新搜索。 if(abs(g_irig_old_interval - 8) > GPS_SIGAL_DIFF) { g_signal_valid = 0; g_irig_code_index = 0; goto __ret; } //保存P码 g_irig_code[g_irig_code_index++] = GPS_IRIG_CODE_P; if(g_irig_code_index == 1 && g_signal_valid == 1) { //分板对时下降沿 //GPIO_GPS_LOW(); //修正时间 tmp_sys_time.ms = (unsigned short)((tmp_sys_time.ms+500)/1000*1000); _ms_update_time(); //修正边沿 MCF_REG32(MCF_DTIM_DTER(CFG_DTIM_GPS_CAP)) = MCF_DTIM_DTER_REF; g_1s_refence = capture_value + 1000000; MCF_REG32(MCF_DTIM_DTRR(CFG_DTIM_GPS_CAP)) = g_1s_refence; } goto __ret; } //保存编码 switch(g_irig_old_interval) { case 1: case 2: case 3: g_irig_code[g_irig_code_index++] = GPS_IRIG_CODE_0; break; case 4: case 5: case 6: g_irig_code[g_irig_code_index++] = GPS_IRIG_CODE_1; break; case 7: case 8: case 9: g_irig_code[g_irig_code_index++] = GPS_IRIG_CODE_P; break; default: rt_printf("gps:g_irig_old_interval=%d!\r\n",g_irig_old_interval); g_signal_valid = 0; g_irig_code_index = 0; goto __ret; break; } //如果接收完时间信息,就开始处理 if(g_irig_code_index >= 100) { if(_gps_irig_decode(&g_irig_code[1],&tmp_sys_time) == 0) { g_signal_valid = 1; g_keep_alive_gps = CLOCK_ALIVE_GPS; } else g_signal_valid = 0; g_irig_code_index = 0; } __ret: g_irig_old_value = capture_value; g_irig_old_interval = interval; #endif } /*------------------------------ 测试函数 ------------------------------------- */ #ifdef _DEBUG_GPS #include "ustimer.h" int gps_test(void) { unsigned int us0, t; rt_printf("gps_test start...\r\n"); // rt_irq_level(0); t = 0; us0 = ustimer_get_origin(); // sunxi 20220424 while(1) ; while (t < 10) { // rt_printf("pit(t=%03dsec):g_gps_ms:%06d,diff(g_gps_ms-t*1000):%d!\r\n",t,g_gps_ms,g_gps_ms -t*1000); rt_printf("g_sys_time: %04d-%02d-%02d time: %02d:%02d:%05d!\r\n", tmp_sys_time.year + 2000, tmp_sys_time.month, tmp_sys_time.day, tmp_sys_time.hour, tmp_sys_time.min, tmp_sys_time.ms); ustimer_delay_origin(us0, ++t * USTIMER_SEC); } rt_printf("gps_test end...\r\n"); return 0; } #endif