Elson Ong
Newbie level 3
- Joined
- Mar 2, 2013
- Messages
- 3
- Helped
- 0
- Reputation
- 0
- Reaction score
- 0
- Trophy points
- 1,281
- Activity points
- 1,689
I used PIC16F877A, software MPLAB IDE v.8.89 and build with compiler v.9.70. with Error [192] D:\GPRSv1_1\GPRSv1_1\GPRSv1\GPRSv1.c; 48.1 undefined identifier "OPTION_REGbits". Does anyone can help to enlighten me on this? Thanks a lot ^^
#include "GPRSv1.h"
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//configuration
//================================================== ========================
__CONFIG(0x3F32); //configuration for the microcontroller
//global variables
//================================================== ========================
char buffer[96];
char outbuf[80];
char minute_flag = 1;
char seconds = 0;
// Initialization
void init(void)
{
//set I/O input output
TRISB = 0b00000011; //configure PORTB I/O direction
TRISD = 0b00000000; //configure PORTD I/O direction
TRISA = 0b00001111; //configure PORTA I/O direction
//setup ADC
ADRESH = 0; //clear A/D result
ADRESL = 0; //clear A/D result
ADCON1 = 0b11000100; // A/D result right justified,
// configure RA0, RA1 and RA3 as analog inputs
//setup Timer 0
OPTION_REGbits.T0CS = 0; //use internal clock
OPTION_REGbits.PSA = 0; //assign prescaler to timer
OPTION_REGbits.PS = 0b111; //prescaler 1:256
TMR0 = -TIMER_CYCLE; //set to 10ms interrupt
//setup UART
SPBRG=10; //set baud rate as 115200 baud
TXSTAbits.BRGH=1; //baud rate high speed option
TXSTAbits.TXEN=1; //enable transmission
TXSTAbits.TX9 =0; //8-bit transmission
RCSTAbits.RX9 =0; //8-bit reception
RCSTAbits.CREN=1; //enable reception
RCSTAbits.SPEN=1; //enable serial port
//setup interrupt
INTCONbits.GIE = 1; //enable global interrupt
INTCONbits.PEIE = 1; //enable peripheral interrupt
INTCONbits.TMR0IF = 0; //enable timer 0 interrupt
INTCONbits.TMR0IE = 1;
PIR1bits.RCIF = 0; //enable UART interrupt
PIE1bits.RCIE = 1;
//configure lcd
lcd_send_config(0b00000001); //clear display at lcd
lcd_send_config(0b00000010); //lcd return to home
lcd_send_config(0b00000110); //entry mode-cursor increase 1
lcd_send_config(0b00001100); //display on, cursor off and cursor blink off
lcd_send_config(0b00111000); //function set
//display startup message
lcd_clr(); //clear lcd
lcd_send_string(BANNER1); //display Banner 1
lcd_goto(20); //set the lcd cursor to location 20
lcd_send_string(BANNER2); //display Banner 2
//blink LEDs once
LED1 = LED2 = 1; //switch on LEDs
delay(125000); //delay 1 second
LED1 = LED2 = 0; //switch off LEDs
}
// Entry point
void main(void)
{
init();
LED1 = 1; LED2 = 0;
if (!gsm_ping()) {
lcd_clr();
lcd_send_string("No GSM Device");
delay(7500000); // delay 1 minute, then reset to try again.
reset();
}
#ifdef GSM_SIMPIN
gsm_cpin_write(GSM_SIMPIN);
pause();
#endif
if (!gsm_cpin_read()) {
lcd_clr();
lcd_send_string("SIM card error");
delay(7500000); // delay 1 minute, then reset to try again.
reset();
}
while (!gsm_cgatt_write(1)) {
lcd_clr();
lcd_send_string("No network");
delay(1250000); // delay 10 seconds, then try again.
}
lcd_clr();
lcd_send_string("Network ready");
gsm_cmgf_write(1);
gsm_ciphead_write(1);
gsm_cdnsorip_write(1);
gsm_cipsprt_write(1);
char retry_count = 0;
while (1) {
if (retry_count != 0) {
lcd_clr();
lcd_send_string("Connection error");
lcd_goto(20);
lcd_send_string("Retry in 10 secs");
delay(1250000); // delay 10 seconds
}
if (++retry_count > GSM_MAX_RETRY) {
lcd_clr();
lcd_send_string("Connection error");
lcd_goto(20);
lcd_send_string("Give up retrying");
gsm_cmgs_write(GSM_DEST_NO, STATION_ID ": Network Error. "
"Max retries exceeded. Reply \""
STATION_ID " RESET\" to reset device.");
while (1) {
delay(7500000); // delay 1 minute.
// Wait for SMS, then reset.
char *from = &outbuf[40];
char *message;
char i;
for (i = 1; i <= 30; i++) {
message = gsm_cmgr_write(i, from);
if (message != NULL) {
char match = (strcmp(message, STATION_ID " RESET") == 0)
&& (strcmp(from, GSM_DEST_NO) == 0);
pause();
pause();
gsm_cmgd_write(i);
pause();
if (match) reset();
} else {
pause();
pause();
}
}
}
}
lcd_clr();
lcd_send_string("Connecting...");
gsm_cgact_write(1, 0);
gsm_cipshut_exec();
if (!gsm_cgdcont_write(1, GSM_APN)) continue;
if (!gsm_cgact_write(1, 1)) continue;
if (!gsm_cstt_write(GSM_APN, GSM_USERNAME, GSM_PASSWORD)) continue;
if (!gsm_cdnscfg_write(GSM_DNS_PRI_SERVER, GSM_DNS_SEC_SERVER)) continue;
if (!gsm_ciicr_exec()) continue;
if (gsm_cifsr_exec() == NULL) continue;
char *status = gsm_cipstatus_exec();
if (status == NULL) continue;
if (strncmp(status, "PDP DEACT", 9) == 0) continue;
if (gsm_cdnsgip_write(GSM_SERVER_DOMAIN) == NULL) continue;
lcd_clr();
lcd_send_string("Connected");
while (1) {
if (!minute_flag) {
sprintf(outbuf, "%u seconds", 60 - seconds);
lcd_clr();
lcd_send_string("Next update in");
lcd_goto(20);
lcd_send_string(outbuf);
pause();
continue;
}
minute_flag = 0;
/* ADC sampling and conversion */
unsigned short ch0, ch1, ch3;
ADCON0 = CHANNEL0; // select channel 0
ch0 = (float)read_adc() * (5000.0 / 1024); // convert output to mV
ADCON0 = CHANNEL1; // select channel 1
ch1 = (float)read_adc() * (5000.0 / 1024); // convert output to mV
ADCON0 = CHANNEL3; // select channel 3
ch3 = (float)read_adc() * (5000.0 / 1024); // convert output to mV
if (!gsm_cipstart_write("TCP", GSM_SERVER_DOMAIN, GSM_SERVER_PORT)) {
break;
}
lcd_clr();
lcd_send_string("Sending data...");
gsm_cipsend_exec(0, "");
sprintf(outbuf, "GET /?StationId=%s&Magnitude=%i.%.3i HTTP/1.1",
STATION_ID, ch0 / 1000, ch0 % 1000);
gsm_cipsend_exec(1, outbuf);
gsm_cipsend_exec(2, "Host: " GSM_SERVER_DOMAIN);
gsm_cipsend_exec(3, "Connection: Keep-Alive");
gsm_cipsend_exec(4, "Accept: */*");
gsm_cipsend_exec(5, "Accept-Language: en-us");
gsm_cipsend_exec(6, "");
if (!gsm_cipsend_exec(255, "")) {
break;
}
lcd_clr();
lcd_send_string("Data sent");
delay(3750000); // wait 30 seconds for all data to arrive.
gsm_cipclose_exec();
retry_count = 1; // reset retry count, since we have successfully sent data.
}
}
// Code for testing purpose.
while (1) {
if (SW1 == 0) {
if (gsm_ping()) {
LED1 = 1;
LED2 = 1;
}
delay(125000);
} else if (SW2 == 0) {
char *from = &outbuf[40];
char *message;
char i;
for (i = 1; i <= 30; i++) {
message = gsm_cmgr_write(i, from);
if (message != NULL) {
if ((strcmp(message, STATION_ID " RESET") == 0) &&
(strcmp(from, GSM_DEST_NO) == 0)) {
LED1 = 0; LED2 = 1;
break;
}
} else {
pause();
}
pause();
pause();
}
delay(125000);
}
}
}
// Coarse delay function (125000 unit = 1 second approx.)
void delay(unsigned long delay_unit)
{
while (delay_unit--);
}
void pause()
{
delay(2000);
}
// Pseudo-random number generator. May not be accurate.
char random()
{
return TMR0;
}
// Software reset
void reset()
{
PCLATH = 0x00;
PCL = 0x00;
}
// interrupt service routine
//================================================== ========================
void serial_isr(void)
{
unsigned char c = RCREG;
}
void timer_isr(void)
{
static char counter = 0;
if (++counter == 100) {
LED1 ^= 1;
LED2 ^= 1;
counter = 0;
if (++seconds == 60) {
minute_flag = 1;
seconds = 0;
}
}
}
void interrupt my_isr(void)
{
if ((TMR0IE) && (TMR0IF)) {
timer_isr();
TMR0 = -TIMER_CYCLE;
TMR0IF = 0;
} else if ((RCIE) && (RCIF)) {
serial_isr();
RCIF = 0;
}
}
// GSM Modem Wrapper functions
// Divided into four types: Test, Read, Write, Execute
// Suffix are added to the function names: _test, _read, _write, _exec
// to indicate its command type.
// So a function name is built up of ('gsm_' + AT command + suffix).
//================================================== ========================
// Ping whether device exists. Return 1 if success, 0 if failed.
char gsm_ping()
{
gsm_execute("AT", 1);
return (strncmp(buffer, "OK", 2) == 0);
}
// Read SIM Card lock state. Return 1 if ready, 0 if locked or unready.
char gsm_cpin_read()
{
gsm_execute("AT+CPIN?", 1);
return (strncmp(buffer, "+CPIN: READY", 12) == 0);
}
char gsm_cpin_write(unsigned int pin_no)
{
sprintf(outbuf, "AT+CPIN=%u", pin_no);
gsm_execute(outbuf, 1);
return (strncmp(buffer, "OK", 2) == 0);
}
//-------- SMS commands --------//
// Delete SMS message. Return 1 if success, 0 if failed.
char gsm_cmgd_write(char index)
{
sprintf(outbuf, "AT+CMGD=%u", index);
gsm_execute(outbuf, 1);
return (strncmp(buffer, "OK", 2) == 0);
}
// Read and return sms format (0 - PDU mode, 1 - text mode, [-1] - unreadable)
char gsm_cmgf_read()
{
gsm_execute("AT+CMGF?", 1);
if (strncmp(buffer, "+CMGF:", 6) == 0) {
return atoi(buffer+7);
} else {
return -1;
}
}
// Write sms format (0 - PDU mode, 1 - text mode). Return 1 if success, 0 if failed.
char gsm_cmgf_write(char format)
{
sprintf(outbuf, "AT+CMGF=%u", format);
gsm_execute(outbuf, 1);
return (strncmp(buffer, "OK", 2) == 0);
}
// List all stored sms. Filter can be 'all', 'rec unread', 'rec read',
// 'sto unsent', or 'sto sent'.
void gsm_cmgl_write(const char *filter)
{
sprintf(outbuf, "AT+CMGL=\"%.10s\"", filter);
gsm_execute(outbuf, 1);
}
// Read sms refered by index.
char * gsm_cmgr_write(char index, char *from)
{
from[0] = 0;
sprintf(outbuf, "AT+CMGR=%u", index);
gsm_execute(outbuf, 1);
if (strncmp(buffer, "+CMGR:", 6) == 0) {
char *pos = strchr(buffer, '"');
pos = strchr(pos + 1, '"');
pos = strchr(pos + 1, '"');
*(strchr(pos + 1, '"')) = 0;
strcpy(from, pos + 1);
pause();
gsm_execute(outbuf, 1);
gsm_read_more(1);
*(strchr(buffer, '\r')) = 0;
return buffer;
}
return NULL;
}
// Send sms. Return 1 if success, 0 if failed.
char gsm_cmgs_write(const char *hp_number, const char *message)
{
sprintf(outbuf, "AT+CMGS=\"%s\"", hp_number);
RCIE = 0;
gsm_send_command(outbuf);
unsigned char rcv_data = uart_rec();
RCIE = 1;
if (rcv_data == '>') {
sprintf(outbuf, "%s%c", message, 26); // message + 26(Ctrl Z)
gsm_execute(outbuf, 1);
return (strncmp(buffer, "+CMGS:", 6) == 0);
} else {
return 0;
}
}
//-------- GPRS commands --------//
// Read network state (1 - attached, 0 - detached, [-1] - read failed)
char gsm_cgatt_read()
{
gsm_execute("AT+CGATT?", 1);
if (strncmp(buffer, "+CGATT:", 7) == 0) {
return atoi(buffer+8);
} else {
return -1;
}
}
// Set network state. Return 1 if success, 0 if failed.
char gsm_cgatt_write(char state)
{
sprintf(outbuf, "AT+CGATT=%u", state);
gsm_execute(outbuf, 1);
return (strncmp(buffer, "OK", 2) == 0);
}
// Read PDP context settings. Return 1 if success, 0 if failed.
char gsm_cgdcont_read()
{
gsm_execute("AT+CGDCONT?", 1);
return (strncmp(buffer, "+CGDCONT:", 9) == 0) ||
(strncmp(buffer, "OK", 2) == 0);
}
// Write settings to PDP context. Return 1 if success. 0 if failed.
char gsm_cgdcont_write(char cid, const char *apn)
{
sprintf(outbuf, "AT+CGDCONT=%u,\"IP\",\"%s\"", cid, apn);
gsm_execute(outbuf, 1);
return (strncmp(buffer, "OK", 2) == 0);
}
// Read PDP status. (1 - activated, 0 - deactivated, [-1] - read failed)
char gsm_cgact_read(char cid)
{
gsm_execute("AT+CGACT?", 1);
while (strncmp(buffer, "+CGACT:", 7) == 0) {
if (cid == atoi(buffer + 8)) {
char * pos = strchr(buffer + 8, ',');
if (pos != NULL) {
return atoi(pos+1);
} else {
return -1;
}
} else {
gsm_read_more(1);
}
}
return -1;
}
// Set PDP status. Return 1 if success, 0 if failed.
char gsm_cgact_write(char cid, char state)
{
sprintf(outbuf, "AT+CGACT=%u,%u", state, cid);
gsm_execute(outbuf, 1);
return (strncmp(buffer, "OK", 2) == 0) ||
(strncmp(buffer, "NO CARRIER", 10) == 0);
}
// Read and return pdp address. Otherwise, return NULL if failed.
char * gsm_cgpaddr_write(char cid)
{
sprintf(outbuf, "AT+CGPADDR=%u", cid);
gsm_execute(outbuf, 1);
char * pos = strchr(buffer, ',');
if (pos != NULL) {
pos[17] = 0;
return pos + 2;
} else {
return NULL;
}
}
//-------- TCPIP commands --------//
// Start up tcp or udp connection. Return 1 if success, 0 if failed.
char gsm_cipstart_write(const char *mode, const char *address, unsigned int port)
{
sprintf(outbuf, "AT+CIPSTART=\"%s\",\"%s\",\"%u\"", mode, address, port);
gsm_execute(outbuf, 1);
if (strncmp(buffer, "OK", 2) == 0) {
gsm_read_more(2);
char *pos = strchr(buffer, '\n');
if (pos != NULL) {
pos += 1;
return (strncmp(pos, "CONNECT OK", 10) == 0);
}
}
return 0;
}
// Send data through tcp or udp connection.
// When line = 0, send AT+CIPSEND command.
// When 0 < line < 255, send data line.
// When line = 255, send termination character Ctrl+Z(26).
// Return 1 if success, 0 if failed.
char gsm_cipsend_exec(char line, const char *data)
{
if (line == 0) {
gsm_execute("AT+CIPSEND", 0);
return 1;
} else if (line == 255) {
gsm_execute("\x1A", 1);
return (strncmp(buffer, "SEND OK", 7) == 0);
} else {
gsm_execute(data, 0);
return 1;
}
}
// Close tcp or udp connection. Return 1 if success, 0 if failed.
char gsm_cipclose_exec()
{
gsm_execute("AT+CIPCLOSE", 1);
return (strncmp(buffer, "CLOSE OK", 8) == 0);
}
// Deactivate PDP context. Return 1 if success, 0 if failed.
char gsm_cipshut_exec()
{
gsm_execute("AT+CIPSHUT", 1);
return (strncmp(buffer, "SHUT OK", 7) == 0);
}
// Set local port. Return 1 if success, 0 if failed.
char gsm_clport(const char *mode, unsigned int port)
{
sprintf(outbuf, "AT+CLPORT=\"%s\",%u", mode, port);
gsm_execute(outbuf, 1);
return (strncmp(buffer, "OK", 2) == 0);
}
// Start task and set apn, username, password. Return 1 if success, 0 if failed.
char gsm_cstt_write(const char *apn, const char *username, const char *password)
{
sprintf(outbuf, "AT+CSTT=\"%s\",\"%s\",\"%s\"", apn, username, password);
gsm_execute(outbuf, 1);
return (strncmp(buffer, "OK", 2) == 0);
}
// Start task. Return 1 if success, 0 if failed.
char gsm_cstt_exec()
{
gsm_execute("AT+CSTT", 1);
return (strncmp(buffer, "OK", 2) == 0);
}
// Bring up wireless connecion. Return 1 if success, 0 if failed.
char gsm_ciicr_exec()
{
gsm_execute("AT+CIICR", 1);
return (strncmp(buffer, "OK", 2) == 0);
}
// Read and return local ip address. Otherwise, return NULL if failed.
char * gsm_cifsr_exec()
{
gsm_execute("AT+CIFSR", 1);
if (strncmp(buffer, "ERROR", 5) == 0) {
return NULL;
} else {
*(strchr(buffer, '\r')) = 0;
return buffer;
}
}
// Query current connection status. Otherwise, return NULL if failed.
char * gsm_cipstatus_exec()
{
gsm_execute("AT+CIPSTATUS", 3);
char *pos = strstr(buffer, "STATE: ");
if (pos != NULL) {
pos += 7;
*(strchr(pos, '\r')) = 0;
return pos;
} else {
return NULL;
}
}
// Configure domain name server. Return 1 if success, 0 if failed.
char gsm_cdnscfg_write(const char *pri_dns, const char *sec_dns)
{
sprintf(outbuf, "AT+CDNSCFG=\"%s\",\"%s\"", pri_dns, sec_dns);
gsm_execute(outbuf, 1);
return (strncmp(buffer, "OK", 2) == 0);
}
// Query ip address of given domain name. Otherwise, return NULL if failed.
char * gsm_cdnsgip_write(const char *domain_name)
{
sprintf(outbuf, "AT+CDNSGIP=\"%s\"", domain_name);
gsm_execute(outbuf, 1);
if (strncmp(buffer, "OK", 2) == 0) {
gsm_read_more(2);
char *pos = strchr(buffer, '\n');
if (pos != NULL) {
pos += 1;
*(strchr(pos, '\r')) = 0;
}
return pos;
} else {
return NULL;
}
}
// Select which method to use in AT+CIPSTART (0 - IP address, 1 - domain name)
// Return 1 if success, 0 if failed.
char gsm_cdnsorip_write(char mode)
{
sprintf(outbuf, "AT+CDNSORIP=%u", mode);
gsm_execute(outbuf, 1);
return (strncmp(buffer, "OK", 2) == 0);
}
// Set whether to add IP head when rcv data. Return 1 if success, 0 if failed.
char gsm_ciphead_write(char mode)
{
sprintf(outbuf, "AT+CIPHEAD=%u", mode);
gsm_execute(outbuf, 1);
return (strncmp(buffer, "OK", 2) == 0);
}
// Set prompt of '>' when sending data. Return 1 if success, 0 if failed.
char gsm_cipsprt_write(char mode)
{
sprintf(outbuf, "AT+CIPSPRT=%u", mode);
gsm_execute(outbuf, 1);
return (strncmp(buffer, "OK", 2) == 0);
}
// Configure as a server. Return 1 if success, 0 if failed.
char gsm_cipserver_exec()
{
gsm_execute("AT+CIPSERVER", 1);
if (strncmp(buffer, "OK", 2) == 0) {
gsm_read_more(2);
char *pos = strchr(buffer, '\n');
if (pos != NULL) {
pos += 1;
return (strncmp(pos, "SERVER OK", 9) == 0);
}
}
return 0;
}
// Set CSD or GPRS for connection mode. Return 1 if success, 0 if failed.
char gsm_cipcsgp_write(char mode, const char *apn, const char *username, const char *password)
{
sprintf(outbuf, "AT+CIPCSGP=%u,\"%s\",\"%s\",\"%s\"", mode, apn, username, password);
gsm_execute(outbuf, 1);
return (strncmp(buffer, "OK", 2) == 0);
}
// Choose connection (1 - client, 2 - server). Return 1 if success, 0 if failed.
char gsm_cipccon_write(char connection)
{
sprintf(outbuf, "AT+CIPCCON=%u", connection);
gsm_execute(outbuf, 1);
return (strncmp(buffer, "OK", 2) == 0);
}
// Set whether fix the local port. Return 1 if success, 0 if failed.
char gsm_cipflp_write(char mode)
{
sprintf(outbuf, "AT+CIPFLP=%u", mode);
gsm_execute(outbuf, 1);
return (strncmp(buffer, "OK", 2) == 0);
}
// Save TCPIP application context. Return 1 if success, 0 if failed.
char gsm_cipscont_exec()
{
gsm_execute("AT+CIPSCONT", 1);
return (strncmp(buffer, "OK", 2) == 0);
}
// Select TCPIP application mode (0 - normal, 1 - tcp channel mode).
// Return 1 if success, 0 if failed.
char gsm_cipmode_write(char mode)
{
sprintf(outbuf, "AT+CIPMODE=%u", mode);
gsm_execute(outbuf, 1);
return (strncmp(buffer, "OK", 2) == 0);
}
// send and store result from gsm command
unsigned char gsm_execute(const char *command, unsigned char nlines)
{
unsigned char rcv_len = 0;
RCIE = 0;
gsm_send_command(command);
buffer[0] = 0;
while (nlines--) {
rcv_len += gsm_read_line(buffer + rcv_len);
}
RCIE = 1;
buffer[rcv_len] = 0;
return rcv_len;
}
// read some more lines after gsm_execute.
unsigned char gsm_read_more(unsigned char nlines)
{
unsigned char rcv_len = 0;
RCIE = 0;
buffer[0] = 0;
while (nlines--) {
rcv_len += gsm_read_line(buffer + rcv_len);
}
RCIE = 1;
buffer[rcv_len] = 0;
return rcv_len;
}
// UART helper functions
//================================================== ========================
unsigned char uart_rec(void) //receive uart value
{
unsigned char rec_data;
while(RCIF==0); //wait for data
rec_data = RCREG;
return rec_data; //return the data received
}
void uart_send(unsigned char data)
{
while(TXIF==0); //only send the new data after
TXREG=data; //the previous data finish sent
}
void uart_str(const char *s)
{
while(*s)uart_send(*s++);
}
void gsm_send_command(const char *command)
{
unsigned char rec_data;
while (*command != 0)
{
uart_send(*command++); // Send the AT command.
rec_data = uart_rec(); // Read the echo.
}
// Send <ENTER>.
uart_str("\r\n");
// Read the echo until Line Feed character is received.
do {
rec_data = uart_rec();
} while (rec_data != '\n');
}
unsigned char gsm_read_line(char *buffer)
{
unsigned char rec_data;
unsigned char rec_len = 0;
// Read the data until Line Feed character is received.
do {
rec_data = uart_rec();
*buffer++ = rec_data;
++rec_len;
} while (rec_data != '\n' && rec_len < 80);
// return the length of data received.
return rec_len;
}
// LCD Display functions
//================================================== ========================
void lcd_send_config(unsigned char data) //send lcd configuration
{
rs=0; //set lcd to configuration mode
lcd_data=data; //lcd data port = data
e=1; //pulse e to confirm the data
delay(50);
e=0;
delay(50);
}
void lcd_send_char(unsigned char data) //send lcd character
{
rs=1; //set lcd to display mode
lcd_data=data; //lcd data port = data
e=1; //pulse e to confirm the data
delay(10);
e=0;
delay(10);
}
void lcd_goto(unsigned char data) //set the location of the lcd cursor
{ //if the given value is (0-15) the
if(data<16) //cursor will be at the upper line
{ //if the given value is (20-35) the
lcd_send_config(0x80+data); //cursor will be at the lower line
} //location of the lcd cursor(2X16):
else // -----------------------------------------------------
{ // | |00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15| |
data=data-20; // | |20|21|22|23|24|25|26|27|28|29|30|31|32|33|34|35| |
lcd_send_config(0xc0+data); // -----------------------------------------------------
}
}
void lcd_clr(void) //clear the lcd
{
lcd_send_config(0x01);
delay(600);
}
void lcd_send_string(const char *s) //send a string to display in the lcd
{
while (s && *s) lcd_send_char (*s++);
}
// ADC helper functions
//================================================== ========================
unsigned short read_adc(void)
{
unsigned short i;
unsigned short result;
unsigned long result_temp=0;
for(i=2000;i>0;i-=1) //looping 2000 times for getting average value
{
ADCON0bits.GO = 1; //ADGO is the bit 2 of the ADCON0 register
while(ADCON0bits.GO==1); //ADC start, ADGO=0 after finish ADC progress
result=ADRESH;
result=result<<8; //shift to left for 8 bit
result=result|ADRESL; //10 bit result from ADC
result_temp+=result;
}
result = result_temp/2000; //getting average value
return result;
}
#include "GPRSv1.h"
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//configuration
//================================================== ========================
__CONFIG(0x3F32); //configuration for the microcontroller
//global variables
//================================================== ========================
char buffer[96];
char outbuf[80];
char minute_flag = 1;
char seconds = 0;
// Initialization
void init(void)
{
//set I/O input output
TRISB = 0b00000011; //configure PORTB I/O direction
TRISD = 0b00000000; //configure PORTD I/O direction
TRISA = 0b00001111; //configure PORTA I/O direction
//setup ADC
ADRESH = 0; //clear A/D result
ADRESL = 0; //clear A/D result
ADCON1 = 0b11000100; // A/D result right justified,
// configure RA0, RA1 and RA3 as analog inputs
//setup Timer 0
OPTION_REGbits.T0CS = 0; //use internal clock
OPTION_REGbits.PSA = 0; //assign prescaler to timer
OPTION_REGbits.PS = 0b111; //prescaler 1:256
TMR0 = -TIMER_CYCLE; //set to 10ms interrupt
//setup UART
SPBRG=10; //set baud rate as 115200 baud
TXSTAbits.BRGH=1; //baud rate high speed option
TXSTAbits.TXEN=1; //enable transmission
TXSTAbits.TX9 =0; //8-bit transmission
RCSTAbits.RX9 =0; //8-bit reception
RCSTAbits.CREN=1; //enable reception
RCSTAbits.SPEN=1; //enable serial port
//setup interrupt
INTCONbits.GIE = 1; //enable global interrupt
INTCONbits.PEIE = 1; //enable peripheral interrupt
INTCONbits.TMR0IF = 0; //enable timer 0 interrupt
INTCONbits.TMR0IE = 1;
PIR1bits.RCIF = 0; //enable UART interrupt
PIE1bits.RCIE = 1;
//configure lcd
lcd_send_config(0b00000001); //clear display at lcd
lcd_send_config(0b00000010); //lcd return to home
lcd_send_config(0b00000110); //entry mode-cursor increase 1
lcd_send_config(0b00001100); //display on, cursor off and cursor blink off
lcd_send_config(0b00111000); //function set
//display startup message
lcd_clr(); //clear lcd
lcd_send_string(BANNER1); //display Banner 1
lcd_goto(20); //set the lcd cursor to location 20
lcd_send_string(BANNER2); //display Banner 2
//blink LEDs once
LED1 = LED2 = 1; //switch on LEDs
delay(125000); //delay 1 second
LED1 = LED2 = 0; //switch off LEDs
}
// Entry point
void main(void)
{
init();
LED1 = 1; LED2 = 0;
if (!gsm_ping()) {
lcd_clr();
lcd_send_string("No GSM Device");
delay(7500000); // delay 1 minute, then reset to try again.
reset();
}
#ifdef GSM_SIMPIN
gsm_cpin_write(GSM_SIMPIN);
pause();
#endif
if (!gsm_cpin_read()) {
lcd_clr();
lcd_send_string("SIM card error");
delay(7500000); // delay 1 minute, then reset to try again.
reset();
}
while (!gsm_cgatt_write(1)) {
lcd_clr();
lcd_send_string("No network");
delay(1250000); // delay 10 seconds, then try again.
}
lcd_clr();
lcd_send_string("Network ready");
gsm_cmgf_write(1);
gsm_ciphead_write(1);
gsm_cdnsorip_write(1);
gsm_cipsprt_write(1);
char retry_count = 0;
while (1) {
if (retry_count != 0) {
lcd_clr();
lcd_send_string("Connection error");
lcd_goto(20);
lcd_send_string("Retry in 10 secs");
delay(1250000); // delay 10 seconds
}
if (++retry_count > GSM_MAX_RETRY) {
lcd_clr();
lcd_send_string("Connection error");
lcd_goto(20);
lcd_send_string("Give up retrying");
gsm_cmgs_write(GSM_DEST_NO, STATION_ID ": Network Error. "
"Max retries exceeded. Reply \""
STATION_ID " RESET\" to reset device.");
while (1) {
delay(7500000); // delay 1 minute.
// Wait for SMS, then reset.
char *from = &outbuf[40];
char *message;
char i;
for (i = 1; i <= 30; i++) {
message = gsm_cmgr_write(i, from);
if (message != NULL) {
char match = (strcmp(message, STATION_ID " RESET") == 0)
&& (strcmp(from, GSM_DEST_NO) == 0);
pause();
pause();
gsm_cmgd_write(i);
pause();
if (match) reset();
} else {
pause();
pause();
}
}
}
}
lcd_clr();
lcd_send_string("Connecting...");
gsm_cgact_write(1, 0);
gsm_cipshut_exec();
if (!gsm_cgdcont_write(1, GSM_APN)) continue;
if (!gsm_cgact_write(1, 1)) continue;
if (!gsm_cstt_write(GSM_APN, GSM_USERNAME, GSM_PASSWORD)) continue;
if (!gsm_cdnscfg_write(GSM_DNS_PRI_SERVER, GSM_DNS_SEC_SERVER)) continue;
if (!gsm_ciicr_exec()) continue;
if (gsm_cifsr_exec() == NULL) continue;
char *status = gsm_cipstatus_exec();
if (status == NULL) continue;
if (strncmp(status, "PDP DEACT", 9) == 0) continue;
if (gsm_cdnsgip_write(GSM_SERVER_DOMAIN) == NULL) continue;
lcd_clr();
lcd_send_string("Connected");
while (1) {
if (!minute_flag) {
sprintf(outbuf, "%u seconds", 60 - seconds);
lcd_clr();
lcd_send_string("Next update in");
lcd_goto(20);
lcd_send_string(outbuf);
pause();
continue;
}
minute_flag = 0;
/* ADC sampling and conversion */
unsigned short ch0, ch1, ch3;
ADCON0 = CHANNEL0; // select channel 0
ch0 = (float)read_adc() * (5000.0 / 1024); // convert output to mV
ADCON0 = CHANNEL1; // select channel 1
ch1 = (float)read_adc() * (5000.0 / 1024); // convert output to mV
ADCON0 = CHANNEL3; // select channel 3
ch3 = (float)read_adc() * (5000.0 / 1024); // convert output to mV
if (!gsm_cipstart_write("TCP", GSM_SERVER_DOMAIN, GSM_SERVER_PORT)) {
break;
}
lcd_clr();
lcd_send_string("Sending data...");
gsm_cipsend_exec(0, "");
sprintf(outbuf, "GET /?StationId=%s&Magnitude=%i.%.3i HTTP/1.1",
STATION_ID, ch0 / 1000, ch0 % 1000);
gsm_cipsend_exec(1, outbuf);
gsm_cipsend_exec(2, "Host: " GSM_SERVER_DOMAIN);
gsm_cipsend_exec(3, "Connection: Keep-Alive");
gsm_cipsend_exec(4, "Accept: */*");
gsm_cipsend_exec(5, "Accept-Language: en-us");
gsm_cipsend_exec(6, "");
if (!gsm_cipsend_exec(255, "")) {
break;
}
lcd_clr();
lcd_send_string("Data sent");
delay(3750000); // wait 30 seconds for all data to arrive.
gsm_cipclose_exec();
retry_count = 1; // reset retry count, since we have successfully sent data.
}
}
// Code for testing purpose.
while (1) {
if (SW1 == 0) {
if (gsm_ping()) {
LED1 = 1;
LED2 = 1;
}
delay(125000);
} else if (SW2 == 0) {
char *from = &outbuf[40];
char *message;
char i;
for (i = 1; i <= 30; i++) {
message = gsm_cmgr_write(i, from);
if (message != NULL) {
if ((strcmp(message, STATION_ID " RESET") == 0) &&
(strcmp(from, GSM_DEST_NO) == 0)) {
LED1 = 0; LED2 = 1;
break;
}
} else {
pause();
}
pause();
pause();
}
delay(125000);
}
}
}
// Coarse delay function (125000 unit = 1 second approx.)
void delay(unsigned long delay_unit)
{
while (delay_unit--);
}
void pause()
{
delay(2000);
}
// Pseudo-random number generator. May not be accurate.
char random()
{
return TMR0;
}
// Software reset
void reset()
{
PCLATH = 0x00;
PCL = 0x00;
}
// interrupt service routine
//================================================== ========================
void serial_isr(void)
{
unsigned char c = RCREG;
}
void timer_isr(void)
{
static char counter = 0;
if (++counter == 100) {
LED1 ^= 1;
LED2 ^= 1;
counter = 0;
if (++seconds == 60) {
minute_flag = 1;
seconds = 0;
}
}
}
void interrupt my_isr(void)
{
if ((TMR0IE) && (TMR0IF)) {
timer_isr();
TMR0 = -TIMER_CYCLE;
TMR0IF = 0;
} else if ((RCIE) && (RCIF)) {
serial_isr();
RCIF = 0;
}
}
// GSM Modem Wrapper functions
// Divided into four types: Test, Read, Write, Execute
// Suffix are added to the function names: _test, _read, _write, _exec
// to indicate its command type.
// So a function name is built up of ('gsm_' + AT command + suffix).
//================================================== ========================
// Ping whether device exists. Return 1 if success, 0 if failed.
char gsm_ping()
{
gsm_execute("AT", 1);
return (strncmp(buffer, "OK", 2) == 0);
}
// Read SIM Card lock state. Return 1 if ready, 0 if locked or unready.
char gsm_cpin_read()
{
gsm_execute("AT+CPIN?", 1);
return (strncmp(buffer, "+CPIN: READY", 12) == 0);
}
char gsm_cpin_write(unsigned int pin_no)
{
sprintf(outbuf, "AT+CPIN=%u", pin_no);
gsm_execute(outbuf, 1);
return (strncmp(buffer, "OK", 2) == 0);
}
//-------- SMS commands --------//
// Delete SMS message. Return 1 if success, 0 if failed.
char gsm_cmgd_write(char index)
{
sprintf(outbuf, "AT+CMGD=%u", index);
gsm_execute(outbuf, 1);
return (strncmp(buffer, "OK", 2) == 0);
}
// Read and return sms format (0 - PDU mode, 1 - text mode, [-1] - unreadable)
char gsm_cmgf_read()
{
gsm_execute("AT+CMGF?", 1);
if (strncmp(buffer, "+CMGF:", 6) == 0) {
return atoi(buffer+7);
} else {
return -1;
}
}
// Write sms format (0 - PDU mode, 1 - text mode). Return 1 if success, 0 if failed.
char gsm_cmgf_write(char format)
{
sprintf(outbuf, "AT+CMGF=%u", format);
gsm_execute(outbuf, 1);
return (strncmp(buffer, "OK", 2) == 0);
}
// List all stored sms. Filter can be 'all', 'rec unread', 'rec read',
// 'sto unsent', or 'sto sent'.
void gsm_cmgl_write(const char *filter)
{
sprintf(outbuf, "AT+CMGL=\"%.10s\"", filter);
gsm_execute(outbuf, 1);
}
// Read sms refered by index.
char * gsm_cmgr_write(char index, char *from)
{
from[0] = 0;
sprintf(outbuf, "AT+CMGR=%u", index);
gsm_execute(outbuf, 1);
if (strncmp(buffer, "+CMGR:", 6) == 0) {
char *pos = strchr(buffer, '"');
pos = strchr(pos + 1, '"');
pos = strchr(pos + 1, '"');
*(strchr(pos + 1, '"')) = 0;
strcpy(from, pos + 1);
pause();
gsm_execute(outbuf, 1);
gsm_read_more(1);
*(strchr(buffer, '\r')) = 0;
return buffer;
}
return NULL;
}
// Send sms. Return 1 if success, 0 if failed.
char gsm_cmgs_write(const char *hp_number, const char *message)
{
sprintf(outbuf, "AT+CMGS=\"%s\"", hp_number);
RCIE = 0;
gsm_send_command(outbuf);
unsigned char rcv_data = uart_rec();
RCIE = 1;
if (rcv_data == '>') {
sprintf(outbuf, "%s%c", message, 26); // message + 26(Ctrl Z)
gsm_execute(outbuf, 1);
return (strncmp(buffer, "+CMGS:", 6) == 0);
} else {
return 0;
}
}
//-------- GPRS commands --------//
// Read network state (1 - attached, 0 - detached, [-1] - read failed)
char gsm_cgatt_read()
{
gsm_execute("AT+CGATT?", 1);
if (strncmp(buffer, "+CGATT:", 7) == 0) {
return atoi(buffer+8);
} else {
return -1;
}
}
// Set network state. Return 1 if success, 0 if failed.
char gsm_cgatt_write(char state)
{
sprintf(outbuf, "AT+CGATT=%u", state);
gsm_execute(outbuf, 1);
return (strncmp(buffer, "OK", 2) == 0);
}
// Read PDP context settings. Return 1 if success, 0 if failed.
char gsm_cgdcont_read()
{
gsm_execute("AT+CGDCONT?", 1);
return (strncmp(buffer, "+CGDCONT:", 9) == 0) ||
(strncmp(buffer, "OK", 2) == 0);
}
// Write settings to PDP context. Return 1 if success. 0 if failed.
char gsm_cgdcont_write(char cid, const char *apn)
{
sprintf(outbuf, "AT+CGDCONT=%u,\"IP\",\"%s\"", cid, apn);
gsm_execute(outbuf, 1);
return (strncmp(buffer, "OK", 2) == 0);
}
// Read PDP status. (1 - activated, 0 - deactivated, [-1] - read failed)
char gsm_cgact_read(char cid)
{
gsm_execute("AT+CGACT?", 1);
while (strncmp(buffer, "+CGACT:", 7) == 0) {
if (cid == atoi(buffer + 8)) {
char * pos = strchr(buffer + 8, ',');
if (pos != NULL) {
return atoi(pos+1);
} else {
return -1;
}
} else {
gsm_read_more(1);
}
}
return -1;
}
// Set PDP status. Return 1 if success, 0 if failed.
char gsm_cgact_write(char cid, char state)
{
sprintf(outbuf, "AT+CGACT=%u,%u", state, cid);
gsm_execute(outbuf, 1);
return (strncmp(buffer, "OK", 2) == 0) ||
(strncmp(buffer, "NO CARRIER", 10) == 0);
}
// Read and return pdp address. Otherwise, return NULL if failed.
char * gsm_cgpaddr_write(char cid)
{
sprintf(outbuf, "AT+CGPADDR=%u", cid);
gsm_execute(outbuf, 1);
char * pos = strchr(buffer, ',');
if (pos != NULL) {
pos[17] = 0;
return pos + 2;
} else {
return NULL;
}
}
//-------- TCPIP commands --------//
// Start up tcp or udp connection. Return 1 if success, 0 if failed.
char gsm_cipstart_write(const char *mode, const char *address, unsigned int port)
{
sprintf(outbuf, "AT+CIPSTART=\"%s\",\"%s\",\"%u\"", mode, address, port);
gsm_execute(outbuf, 1);
if (strncmp(buffer, "OK", 2) == 0) {
gsm_read_more(2);
char *pos = strchr(buffer, '\n');
if (pos != NULL) {
pos += 1;
return (strncmp(pos, "CONNECT OK", 10) == 0);
}
}
return 0;
}
// Send data through tcp or udp connection.
// When line = 0, send AT+CIPSEND command.
// When 0 < line < 255, send data line.
// When line = 255, send termination character Ctrl+Z(26).
// Return 1 if success, 0 if failed.
char gsm_cipsend_exec(char line, const char *data)
{
if (line == 0) {
gsm_execute("AT+CIPSEND", 0);
return 1;
} else if (line == 255) {
gsm_execute("\x1A", 1);
return (strncmp(buffer, "SEND OK", 7) == 0);
} else {
gsm_execute(data, 0);
return 1;
}
}
// Close tcp or udp connection. Return 1 if success, 0 if failed.
char gsm_cipclose_exec()
{
gsm_execute("AT+CIPCLOSE", 1);
return (strncmp(buffer, "CLOSE OK", 8) == 0);
}
// Deactivate PDP context. Return 1 if success, 0 if failed.
char gsm_cipshut_exec()
{
gsm_execute("AT+CIPSHUT", 1);
return (strncmp(buffer, "SHUT OK", 7) == 0);
}
// Set local port. Return 1 if success, 0 if failed.
char gsm_clport(const char *mode, unsigned int port)
{
sprintf(outbuf, "AT+CLPORT=\"%s\",%u", mode, port);
gsm_execute(outbuf, 1);
return (strncmp(buffer, "OK", 2) == 0);
}
// Start task and set apn, username, password. Return 1 if success, 0 if failed.
char gsm_cstt_write(const char *apn, const char *username, const char *password)
{
sprintf(outbuf, "AT+CSTT=\"%s\",\"%s\",\"%s\"", apn, username, password);
gsm_execute(outbuf, 1);
return (strncmp(buffer, "OK", 2) == 0);
}
// Start task. Return 1 if success, 0 if failed.
char gsm_cstt_exec()
{
gsm_execute("AT+CSTT", 1);
return (strncmp(buffer, "OK", 2) == 0);
}
// Bring up wireless connecion. Return 1 if success, 0 if failed.
char gsm_ciicr_exec()
{
gsm_execute("AT+CIICR", 1);
return (strncmp(buffer, "OK", 2) == 0);
}
// Read and return local ip address. Otherwise, return NULL if failed.
char * gsm_cifsr_exec()
{
gsm_execute("AT+CIFSR", 1);
if (strncmp(buffer, "ERROR", 5) == 0) {
return NULL;
} else {
*(strchr(buffer, '\r')) = 0;
return buffer;
}
}
// Query current connection status. Otherwise, return NULL if failed.
char * gsm_cipstatus_exec()
{
gsm_execute("AT+CIPSTATUS", 3);
char *pos = strstr(buffer, "STATE: ");
if (pos != NULL) {
pos += 7;
*(strchr(pos, '\r')) = 0;
return pos;
} else {
return NULL;
}
}
// Configure domain name server. Return 1 if success, 0 if failed.
char gsm_cdnscfg_write(const char *pri_dns, const char *sec_dns)
{
sprintf(outbuf, "AT+CDNSCFG=\"%s\",\"%s\"", pri_dns, sec_dns);
gsm_execute(outbuf, 1);
return (strncmp(buffer, "OK", 2) == 0);
}
// Query ip address of given domain name. Otherwise, return NULL if failed.
char * gsm_cdnsgip_write(const char *domain_name)
{
sprintf(outbuf, "AT+CDNSGIP=\"%s\"", domain_name);
gsm_execute(outbuf, 1);
if (strncmp(buffer, "OK", 2) == 0) {
gsm_read_more(2);
char *pos = strchr(buffer, '\n');
if (pos != NULL) {
pos += 1;
*(strchr(pos, '\r')) = 0;
}
return pos;
} else {
return NULL;
}
}
// Select which method to use in AT+CIPSTART (0 - IP address, 1 - domain name)
// Return 1 if success, 0 if failed.
char gsm_cdnsorip_write(char mode)
{
sprintf(outbuf, "AT+CDNSORIP=%u", mode);
gsm_execute(outbuf, 1);
return (strncmp(buffer, "OK", 2) == 0);
}
// Set whether to add IP head when rcv data. Return 1 if success, 0 if failed.
char gsm_ciphead_write(char mode)
{
sprintf(outbuf, "AT+CIPHEAD=%u", mode);
gsm_execute(outbuf, 1);
return (strncmp(buffer, "OK", 2) == 0);
}
// Set prompt of '>' when sending data. Return 1 if success, 0 if failed.
char gsm_cipsprt_write(char mode)
{
sprintf(outbuf, "AT+CIPSPRT=%u", mode);
gsm_execute(outbuf, 1);
return (strncmp(buffer, "OK", 2) == 0);
}
// Configure as a server. Return 1 if success, 0 if failed.
char gsm_cipserver_exec()
{
gsm_execute("AT+CIPSERVER", 1);
if (strncmp(buffer, "OK", 2) == 0) {
gsm_read_more(2);
char *pos = strchr(buffer, '\n');
if (pos != NULL) {
pos += 1;
return (strncmp(pos, "SERVER OK", 9) == 0);
}
}
return 0;
}
// Set CSD or GPRS for connection mode. Return 1 if success, 0 if failed.
char gsm_cipcsgp_write(char mode, const char *apn, const char *username, const char *password)
{
sprintf(outbuf, "AT+CIPCSGP=%u,\"%s\",\"%s\",\"%s\"", mode, apn, username, password);
gsm_execute(outbuf, 1);
return (strncmp(buffer, "OK", 2) == 0);
}
// Choose connection (1 - client, 2 - server). Return 1 if success, 0 if failed.
char gsm_cipccon_write(char connection)
{
sprintf(outbuf, "AT+CIPCCON=%u", connection);
gsm_execute(outbuf, 1);
return (strncmp(buffer, "OK", 2) == 0);
}
// Set whether fix the local port. Return 1 if success, 0 if failed.
char gsm_cipflp_write(char mode)
{
sprintf(outbuf, "AT+CIPFLP=%u", mode);
gsm_execute(outbuf, 1);
return (strncmp(buffer, "OK", 2) == 0);
}
// Save TCPIP application context. Return 1 if success, 0 if failed.
char gsm_cipscont_exec()
{
gsm_execute("AT+CIPSCONT", 1);
return (strncmp(buffer, "OK", 2) == 0);
}
// Select TCPIP application mode (0 - normal, 1 - tcp channel mode).
// Return 1 if success, 0 if failed.
char gsm_cipmode_write(char mode)
{
sprintf(outbuf, "AT+CIPMODE=%u", mode);
gsm_execute(outbuf, 1);
return (strncmp(buffer, "OK", 2) == 0);
}
// send and store result from gsm command
unsigned char gsm_execute(const char *command, unsigned char nlines)
{
unsigned char rcv_len = 0;
RCIE = 0;
gsm_send_command(command);
buffer[0] = 0;
while (nlines--) {
rcv_len += gsm_read_line(buffer + rcv_len);
}
RCIE = 1;
buffer[rcv_len] = 0;
return rcv_len;
}
// read some more lines after gsm_execute.
unsigned char gsm_read_more(unsigned char nlines)
{
unsigned char rcv_len = 0;
RCIE = 0;
buffer[0] = 0;
while (nlines--) {
rcv_len += gsm_read_line(buffer + rcv_len);
}
RCIE = 1;
buffer[rcv_len] = 0;
return rcv_len;
}
// UART helper functions
//================================================== ========================
unsigned char uart_rec(void) //receive uart value
{
unsigned char rec_data;
while(RCIF==0); //wait for data
rec_data = RCREG;
return rec_data; //return the data received
}
void uart_send(unsigned char data)
{
while(TXIF==0); //only send the new data after
TXREG=data; //the previous data finish sent
}
void uart_str(const char *s)
{
while(*s)uart_send(*s++);
}
void gsm_send_command(const char *command)
{
unsigned char rec_data;
while (*command != 0)
{
uart_send(*command++); // Send the AT command.
rec_data = uart_rec(); // Read the echo.
}
// Send <ENTER>.
uart_str("\r\n");
// Read the echo until Line Feed character is received.
do {
rec_data = uart_rec();
} while (rec_data != '\n');
}
unsigned char gsm_read_line(char *buffer)
{
unsigned char rec_data;
unsigned char rec_len = 0;
// Read the data until Line Feed character is received.
do {
rec_data = uart_rec();
*buffer++ = rec_data;
++rec_len;
} while (rec_data != '\n' && rec_len < 80);
// return the length of data received.
return rec_len;
}
// LCD Display functions
//================================================== ========================
void lcd_send_config(unsigned char data) //send lcd configuration
{
rs=0; //set lcd to configuration mode
lcd_data=data; //lcd data port = data
e=1; //pulse e to confirm the data
delay(50);
e=0;
delay(50);
}
void lcd_send_char(unsigned char data) //send lcd character
{
rs=1; //set lcd to display mode
lcd_data=data; //lcd data port = data
e=1; //pulse e to confirm the data
delay(10);
e=0;
delay(10);
}
void lcd_goto(unsigned char data) //set the location of the lcd cursor
{ //if the given value is (0-15) the
if(data<16) //cursor will be at the upper line
{ //if the given value is (20-35) the
lcd_send_config(0x80+data); //cursor will be at the lower line
} //location of the lcd cursor(2X16):
else // -----------------------------------------------------
{ // | |00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15| |
data=data-20; // | |20|21|22|23|24|25|26|27|28|29|30|31|32|33|34|35| |
lcd_send_config(0xc0+data); // -----------------------------------------------------
}
}
void lcd_clr(void) //clear the lcd
{
lcd_send_config(0x01);
delay(600);
}
void lcd_send_string(const char *s) //send a string to display in the lcd
{
while (s && *s) lcd_send_char (*s++);
}
// ADC helper functions
//================================================== ========================
unsigned short read_adc(void)
{
unsigned short i;
unsigned short result;
unsigned long result_temp=0;
for(i=2000;i>0;i-=1) //looping 2000 times for getting average value
{
ADCON0bits.GO = 1; //ADGO is the bit 2 of the ADCON0 register
while(ADCON0bits.GO==1); //ADC start, ADGO=0 after finish ADC progress
result=ADRESH;
result=result<<8; //shift to left for 8 bit
result=result|ADRESL; //10 bit result from ADC
result_temp+=result;
}
result = result_temp/2000; //getting average value
return result;
}