lunes, 21 de marzo de 2011

Reloj NTP y otros Proyectos

Uno de los primeros proyectos fue el Reloj NTP con el PIC y la M2ethBoard.

Programa Principal:

program PICNTP
 
include "enc_ss"        ' modulo donde se implementa el codigo
include "eth_enc28j60"  ' modulo usado por el compilador
 
  dim mymacaddr as byte [6]   ' variables para MAC, IP, DNS,GW,MASCARA, Paquete NTP
  dim myipaddr  as byte [4]
  dim gwipaddr  as byte [4]
  dim dnsipaddr as byte [4]
  dim ipmask    as byte [4]
  dim NTP_Pack  as byte [48]
  dim dum       as byte
 
 sub procedure pausa()   ' Pausa para el retardo NTP y recepcion de Paquetes
  for i=0 to 100
  spi_ethernet_dopacket()  ' aun en la Pausa escuchamos peticiones UDP o TCP
  delay_ms(100)
  spi_ethernet_dopacket()
  next i
 end sub
 
'///////////////////  Datos del Paquete UDP explicacion Gracias a: Andrew Gregory  //////////////////////
'
'http://tools.ietf.org/html/rfc1305
'http://tools.ietf.org/html/rfc867
'
'Byte 0: flags:
' Bits 7-6: Leap Indicate (zero for request)
' Bits 5-3: Version (4)
' Bits 2-0: Mode (i.e. 3 for client (or maybe 1 for symmetric active))
'Byte 1: stratum (zero for request)
'Byte 2: poll (zero for request)
'Byte 3: precision (zero for request)
'Bytes 4-7: root delay (zero for request)
'Bytes 8-11: root dispersion (zero for request)
'Bytes 12-15: reference id (zero for request)
'Bytes 16-23: reference timestamp (zero for request)
'Bytes 24-31: originate timestamp (zero for request)
'Bytes 32-39: receive timestamp (zero for request)
'Bytes 40-47: transmit timestamp (set to current time)
'
'////////////////////////////////////////////////////////////////////////////////////////////
 
 sub procedure req_ntp()     ' Construccion de Paquete NTP
  NTP_Pack[0]= 0x23          ' Enviamos modo Cliente, sin estrato
   for dum=1 to 47           ' Todos los demas Bytes son 0
    NTP_Pack[dum]=0
   next dum
  spi_ethernet_sendudp(IPD,123,123,@NTP_Pack,48) 'Enviamos el paquete NTP al Servidor
 end sub
 
 
 
'//////////////////////////////////// Configuracion de Variables ////////////////////////////
 main:
 
  adcon0=0     ' Sin ADC's, Sin Comparadores PORTA Entrada
  adcon1=15
  cmcon=7
  trisa=255
  porta=0
  
  trisd=0     ' PORTD de Salida =0
  portd=0
  
  mymacaddr[0]= 0x00  ' MAC del PIC
  mymacaddr[1]= 0x00
  mymacaddr[2]= 0x00
  mymacaddr[3]= "M"
  mymacaddr[4]= "A"
  mymacaddr[5]= "X"
  
  myipaddr[0]=20    ' IP del PIC
  myipaddr[1]=0
  myipaddr[2]=4
  myipaddr[3]=20
                     ' Mascara del PIC
  ipmask[0]=255
  ipmask[1]=255
  ipmask[2]=255
  ipmask[3]=0
  
  dnsipaddr[0]=20   'DNS y GW del PIC
  dnsipaddr[1]=0
  dnsipaddr[2]=4
  dnsipaddr[3]=1
  
  gwipaddr[0]=20
  gwipaddr[1]=0
  gwipaddr[2]=4
  gwipaddr[3]=1
  
  IPD[0]=20'148
  IPD[1]=0'243      'IP del Servidor NTP
  IPD[2]=4'7
  IPD[3]=10'30
  
 
  
  LCD_CONFIG(PORTB,7,6,5,4,PORTB,0,2,1)   'Configuramos el PORTB para el LCD
  LCD_OUT(1,1,"INICIALIZANDO")
  DELAY_MS(3000)
  
  spi_init()  'iniciamos SPI en el PIC
  spi_ethernet_init(portc,0,portc,1,mymacaddr,myipaddr,1) 'Configuramos e Iniciamos el Ethernet del PIC
  spi_ethernet_confnetwork(ipmask,gwipaddr,dnsipaddr)
 
  for i=0 to 2   ' Blink para ver si esta vivo Termina con RD7 en ON
   portd.7=0
   delay_ms(500)
   portd.7=1
   delay_ms(500)
  next i
 
  tryntp:                    ' empezamos la recepcion de paquetes
   while true
    spi_ethernet_dopacket()  ' Escuchamos peticiones TCP y UDP
     req_ntp()               ' Pedimos la hora UTC cada 10s.
     cls                     ' Limpiamos el LCD
     lcd_out(1,1,fecha.str1) ' Mostramos en la primer linea el dia, mes y año
     lcd_out(2,1,fecha.str2) ' Mostramos en la segunda linea la Hora sin puntitos
    pausa()                  ' Llamamos a Pausa
    spi_ethernet_dopacket()  ' Escuchamos peticiones TCP y UDP
   wend
 goto tryntp                 ' Loop
end.
MODULO 1:
module enc_ss
 
include "eth_enc28j60_api"        ' modulo del compilador
include "unixtime"
 
dim    getRequest  as byte[20]    ' variables de uso general
       dyna        as byte[30]
       NTPr        as byte[48]    ' Variable donde se guarda los datos provenienes del Server
       txt         as string[20]
       i,l         as byte
  dim  IPD         as byte [4]
 
const httpHeader         as string[31] = "HTTP/1.1 200 OK"+chr(10)+"Content-type: "  ' HTTP header
const httpMimeTypeHTML   as string[13] = "text/html"+chr(10)+chr(10)                 ' HTML MIME type
const httpMimeTypeScript as string[14] = "text/plain"+chr(10)+chr(10)                ' TEXT MIME type
const httpMethod         as string[5]  = "GET /"
 
'/////////////////////////////  ' Pagina a mostrar ////////////////////////////////
const pagina as string [837]=
""+
""+
""+
"PIC NTP"+
""+
""+
"
"+ " "+ " "+ "
"+ "
"+ "Actualice la Configuración "+ "
"+ " "+ ""+ ""+ " "+ " "+ ""+ ""+ " "+ " "+ ""+ " "+ "
"+ "Servidor NTP  "+ "
GMT"+ ""+ chr(43)+ ""+ " - 
 "+ "
"+ ""+ "
"+ ""+ " " '/////////////////////////// Implementacion TCP sub function Spi_Ethernet_UserTCP(dim byref remoteHost as byte[4], dim remotePort, localPort, reqLength as word) as word result=0 if localport<>80 then 'escuchamos puerto 80 result=0 end if for i = 0 to 23 getRequest[i] = Spi_Ethernet_getByte() next i getRequest[i] = 0 i = 0 while (httpMethod[i] <> 0) txt[i] = httpMethod[i] i = i + 1 wend if(memcmp(@getRequest, @txt, 5)<>0) then ' Solo se soporta en metodo GET result = 0 exit end if if(getRequest[5] = "x") then 'Si el byte 5 corresponde a "x" mostramos los valores 'el texto puede interpretarse como javascritp /x result = Spi_Ethernet_putConstString(@httpHeader) ' HTTP header result = result + Spi_Ethernet_putConstString(@httpMimeTypeScript) ' MIME type 'Mostramos Fecha Contruyendo una variable tipo string JS: var= " fecha"; dyna = fecha.str1 txt = "var Fecha= " result = result + Spi_Ethernet_putString(@txt) txt = ""+chr(34) result = result + Spi_Ethernet_putString(@txt) result = result + Spi_Ethernet_putString(@dyna) txt = ""+chr(34) result = result + Spi_Ethernet_putString(@txt) txt = ";" result = result + Spi_Ethernet_putString(@txt) ' Mostramos Hora Contruyendo una variable tipo string JS: var= " Hora"; txt = "var Hora= " result = result + Spi_Ethernet_putString(@txt) dyna = fecha.str2 txt = ""+chr(34) result = result + Spi_Ethernet_putString(@txt) result = result + Spi_Ethernet_putString(@dyna) txt = ""+chr(34) result = result + Spi_Ethernet_putString(@txt) txt = ";" result = result + Spi_Ethernet_putString(@txt) end if if(result = 0) then 'Mostrar por defalt result = Spi_Ethernet_putConstString(@httpHeader) ' HTTP header result = result + Spi_Ethernet_putConstString(@httpMimeTypeHTML) ' HTML MIME type result = result + Spi_Ethernet_putConstString(@pagina) ' Pagina HTML end if end sub '//////////////////////////// Implementacion UDP sub function Spi_Ethernet_UserUDP(dim byref remoteHost as byte[4], dim remotePort, destPort, reqLength as word) as word result = 0 ' reseteo de la funcion if destport = 123 then ' Escuchamos por el puerto 123 para capturar datos NTP for i=0 to 47 NTPr[i]=spi_ethernet_getbyte() 'Grabamos los datos en la variable next i FSR2Ptr = @UTCseg ' Converimos los valores separados en una variable de 32bits POSTINC2 = NTPr[43] POSTINC2 = NTPr[42] POSTINC2 = NTPr[41] INDF2 = NTPr[40] actualdate() ' Llamamos al Procedimiento para convertir la hora. end if end sub end.
Modulo 2:
module UnixTime
 
  dim  diat        as string[3]   ' Variables para convertir a cadena
       mdt         as string[3]
       mes         as string[3]
       yyt         as string[5]
       hht         as string[3]
       mmt         as string[3]
       sst         as string[3]
       UnixTimec    as longword    ' Variable para  tiempo UNIX
       UTCseg      as longword    ' Variable que contiene los segundos UTC de 32bits
     const  USRGMT  = 18000       ' Constante GMT para Mexico
 
structure TIEMPO
     dim ss as byte     ' segundos
     dim mn as byte     ' minutos
     dim hh as byte     ' Horas
     dim md as byte     ' Dia del mes de 1 a 31
     dim wd as byte     ' Dia de la Semana Lunes=1....Domingo=6
     dim mo as byte     ' Mes del año de 1 a 12
     dim yy as word     ' Año YK2
     dim str1 as string[17]   'Donde guardamos la Fecha
     dim str2 as string[16]   'Donde Guardamos la Hora
end structure
 
dim    fecha       as TIEMPO   ' variable para la fecha
 
const offset  = 2208988800     ' Diferencia en segundos entre 1900 y 1970
 
sub procedure cls
   lcd_cmd(lcd_clear)    ' Rutina para limpiar LCD
   delay_ms(200)
end sub
 
'//////////////////////////////////////// Procedimiento Para obtener Fecha en Formato Humano /////////////////////////////
 sub procedure ActualDate()
 
 UnixTimec = ((UTCseg - USRGMT)+ 9) - offset   ' Calculamos el TiempoUnix restando a los segundos UTC el gmt del usuario y el offset UNIX
   Time_epochToDate(UnixTimec,fecha)           ' Obtenemos la fecha actual en Formato Humano
   select case fecha.wd                        ' Escogemos el Dia segun su valor
    case 0
     diat="Lun"
    case 1
     diat="Mar"
    case 2
     diat="Mie"
    case 3
     diat="Jue"
    case 4
     diat="Vie"
    case 5
     diat="Sab"
    case 6
     diat="Dom"
   end select
 
  select case fecha.mo                          'Escogemos el mes segun su valor
    case 1
     mes="Ene"
    case 2
     mes="Feb"
    case 3
     mes="Mar"
    case 4
     mes="Abr"
    case 5
     mes="May"
    case 6
     mes="Jun"
    case 7
     mes="Jul"
    case 8
     mes="Ago"
    case 9
     mes="Sep"
    case 10
     mes="Oct"
    case 11
     mes="Nov"
    case 12
     mes="Dic"
  end select
                             ' convertimos a cadena la Fecha
 bytetostr(fecha.md,mdt)
 wordtostr(fecha.yy,yyt)
 bytetostr(fecha.hh,hht)
 bytetostr(fecha.mn,mmt)
 bytetostr(fecha.ss,sst)
 
fecha.str1= diat             'Asignamos el dia a la variable Fecha.str1 y anexamos despues los demas valores
strcat(fecha.str1,mdt)
strcat(fecha.str1,mes)
strcat(fecha.str1,yyt)
 
fecha.str2= hht              'Asignamos la hora a la variable Fecha.str2 y anexamos despues los demas valores
strcat(fecha.str2,mmt)
strcat(fecha.str2,sst)
 
end sub
end.

Y Aqui unas Imagenes de como se veia:



No hay comentarios:

Publicar un comentario