Interfacing gsm with LPC2148 - arm

I am trying to send a message from my ARM7 LPC2148 board. I have connected a SIM900 GSM Modem to the UART0 of the board. But I am not receiving the message on my phone!!I have put print statements here and there so that I know where the system is and where its stuck. But it prints all the messages. It says message sent even though I have not received any SMS.
Here is the code:
Main code
#include "i2c.h"
#include "LPC214x.H" // LPC2148 MPU Register
#include <stdio.h>
#include "gsm.h"
#include "lcd.h"
#include "buzzer.h"
extern int msgflag;
/* Main Program Start Here */
int main(void)
{
PINSEL0 = 0x00000000; // Enable GPIO on all pins
PINSEL1 = 0x00000000;
PINSEL2 = 0x00000000;
lcd_init(); // Initial LCD
lcd_write_control(0x01); // Clear Display (Clear Display,Set DD RAM Address=0)
goto_cursor(0x00); // Set Cursor Line-1
lcd_print("Accident Alert"); // Display LCD Line-1
// Display LCD Line-2
// Display Delay
// Clear Display (Clear Display,Set DD RAM Address=0)
// Display LCD Line-1
goto_cursor(0x40); // Set Cursor = Line-2
lcd_print("System"); // Display LCD Line-2
delay1(100000000);
gsmperform();
// Loop Print Message to LCD16 x 2 //
// Loop Continue
sendmsg();
msgflag=0;
lcd_write_control(0x01); // Clear Display (Clear Display,Set DD RAM Address=0)
goto_cursor(0x00); // Set Cursor Line-1
lcd_print("Message sent"); // Display LCD Line-1
}
gsm.c
#include<lpc214x.h> /*Header file*/
#include "gsm.h"
#include "lcd.h" //header file
extern unsigned char cmgf[]="AT+CMGF=1"; //Text format in GSM modem
extern unsigned char cmgs[]="AT+CMGS=\"9xxxxxxxxx\""; //Mobile number to which the msg is sent
extern unsigned char msg[]="hello"; //secret code
extern unsigned char readall[]="AT+CMGR=\"REC UNREAD\"\r\n";
extern int blink;
unsigned char content[7];
void txu1(unsigned char data) //Transmit a byte of data through UART1
{
while(!(U1LSR & 0x20)); // Wait until UART1 ready to send character
U1THR = data;
}
unsigned char rxu1()
{
unsigned char p;
while ((U1LSR&0x01)!=1);
p=U1RBR;
return p;
}
unsigned char rxu0()
{
unsigned char p;
while ((U0LSR&0x01)!=1);
p=U0RBR;
return p;
}
void sendstring(unsigned char *p) //Sends a string of data through UART1
{
while(1)
{
if(*p=='\0') break;
txu1(*p++);
}
}
void delaygsm() //delay function
{
int i,j;
for(i=0;i<60000;i++)
for(j=0;j<51;j++);
}
void delay2() //delay function
{
int i,j;
for(i=0;i<60000;i++)
for(j=0;j<200;j++);
}
unsigned char recuart1() //recieves a byte from UART1
{
unsigned char p;
while ((U1LSR&0x01)!=1);
p=U1RBR;
return p;
}
void uart1_irq() __irq //ISR if anything is recieved in UART1, the same is transmitted through UART0
{
unsigned char p;
p=U1RBR;
if(p=='a')
{
sendmsg();
}
VICVectAddr=0;
}
void sendmsg(void)
{
sendstring(msg);
}
void initgsm() //Initialization of UART0,UART1 and ISR
{
U0LCR=0x83;
U0DLL=0x61;
U0DLM=0x00;
U0LCR=0x03;
U1LCR=0x83;
U1DLL=0x61;
U1DLM=0x00;
U1LCR=0x03;
U1IER=0x01;
U1FCR=0x07;
VICIntSelect&=0xffffff7f;
VICVectAddr2=(unsigned int)uart1_irq;
VICIntEnable|=0x00000080;
VICVectCntl2=0x20|7;
}
void gsmperform(void)
{
lcd_write_control(0x01); // Clear Display (Clear Display,Set DD RAM Address=0)
goto_cursor(0x00); // Set Cursor Line-1
lcd_print("begin gsm"); // Display LCD Line-1
PINSEL0|=0x00050005;
PINSEL1|=0x00000000;
PINSEL2|=0x00000000;
initgsm();
sendstring("ATe0\r\n");
delaygsm();
sendstring("AT+CMGD=1,4\r\n");
delaygsm();
sendstring("AT+CNMI=1,0,0,0\r\n");
delaygsm();
lcd_write_control(0x01); // Clear Display (Clear Display,Set DD RAM Address=0)
goto_cursor(0x00); // Set Cursor Line-1
lcd_print("end gsm"); // Display LCD Line-1
}

Break up the problem into three parts - Configuring & sending the command, receiving the correct command, and working together.
Connect your LPC2148 board to a PC, and use a PC terminal program to watch what commands you are sending. Make sure the parts of your program is working correctly. Are you running any optimizing options in your compiler? That will mess up your delay functions for sure. Use a built-in timer to provide the delay, not for loops.
Make sure you are using the correct commands to talk to the GSM card. Connect it to a PC if possible (make sure you convert from logic levels to UART levels if it does not have an RS-232 transceiver on it), or to a kit running an interactive terminal. Make sure your commands actually will send an SMS message with the module you have chosen.
Now connect the kit and the module. By now you should know which signals are actually outputs and which are inputs - RS-232 can be very confusing about this. Most processor UARTs are labelled as DTE (TX==output, RX==input), and I'd expect the comms module labeled as DCE (TX==input, RX==output), which means that you would connect RX<->RX and TX<->TX. If they are both labeled as DTE, then you need a null-modem cable to swap the signals, or do it by hand when attaching the board.

Related

Problems with code to send request and receive response over UART on Atmel SAM L21 Xplained Pro

I'm currently developing a system which involves sending a request string to a sensor device connected via UART to an Atmel SAML21 Xplained Pro board. I'm testing with an Arduino board as the "sensor device", but eventually, it'll be for a Rotronic HC-2 sensor.
The process goes something like this:
MCU sends string { 99RDD} over UART to sensor
-> delay of up to 500ms
-> Response string of 99 bytes sent back via UART
-> Response transmitted to virtual com port on embedded debugger
My issue is that for some reason, I'm either not getting anything sent back, or it's sending back the variable request_msg
I know that the response from the sensor should be 99 bytes of ASCII, and I've tested both the actual sensor, and the Arduino test board over serial connectors to ensure that the readings are coming back correctly.
The software is using Atmel ASF v4.0, which is great when it works, but the documentation is fairly flaky, so I was hoping someone with more experience could point me as to where I'm going wrong in the code.
I have the following code for my main application:
#include "atmel_start.h"
#include "atmel_start_pins.h"
#include <string.h>
static uint8_t example_hello_world[14] = "Hello World!\n";
static uint8_t example_error_msg[13] = "UART Error!\n";
static uint8_t request_msg[24] = "Sending Sensor Request\n";
static uint8_t rotronic_ascii[8] = "{ 99RDD}";
volatile static uint32_t data_arrived = 0;
volatile static uint32_t reading_received = 0;
static void tx_cb_EDBG_COM(const struct usart_async_descriptor *const io_descr)
{
/* Transfer completed */
gpio_toggle_pin_level(LED0);
}
static void rx_cb_EDBG_COM(const struct usart_async_descriptor *const io_descr)
{
/* Receive completed */
data_arrived = 1;
}
static void err_cb_EDBG_COM(const struct usart_async_descriptor *const io_descr)
{
/* error handle */
io_write(&EDBG_COM.io, example_error_msg, 13);
}
static void tx_cb_COM1(const struct usart_async_descriptor *const io_descr)
{
/* Transfer completed */
gpio_toggle_pin_level(LED0);
}
static void rx_cb_COM1(const struct usart_async_descriptor *const io_descr)
{
/* Receive completed */
reading_received = 1;
}
static void err_cb_COM1(const struct usart_async_descriptor *const io_descr)
{
/* error handle */
io_write(&COM1.io, example_error_msg, 13);
}
int main(void)
{
volatile uint8_t recv_char[99];
atmel_start_init();
// Setup the EDBG Serial Port
usart_async_register_callback(&EDBG_COM, USART_ASYNC_TXC_CB, tx_cb_EDBG_COM);
usart_async_register_callback(&EDBG_COM, USART_ASYNC_RXC_CB, rx_cb_EDBG_COM);
usart_async_register_callback(&EDBG_COM, USART_ASYNC_ERROR_CB, err_cb_EDBG_COM);
usart_async_enable(&EDBG_COM);
// Send a test string to ensure EDBG Serial is working
io_write(&EDBG_COM.io, example_hello_world, 14);
// Setup the Rotronic [Arduino] Serial Port
usart_async_register_callback(&COM1, USART_ASYNC_TXC_CB, tx_cb_COM1);
usart_async_register_callback(&COM1, USART_ASYNC_RXC_CB, rx_cb_COM1);
usart_async_register_callback(&COM1, USART_ASYNC_ERROR_CB, err_cb_COM1);
usart_async_enable(&COM1);
while (1) {
if (reading_received == 0)
{
// Delay for a Bit
delay_ms(5000);
// Notify the EDBG COM Port
io_write(&EDBG_COM.io, request_msg, 24);
// Send the Rotronic ASCII
io_write(&COM1.io, rotronic_ascii, 8);
}
// Check if Reading has been Received
if (reading_received == 1)
{
while (io_read(&COM1.io, &recv_char, 99) == 99)
{
// Write what's on the buffer from the receiver
io_write(&EDBG_COM.io, recv_char, 99);
}
// Reset the flag
reading_received = 0;
}
}
}
You seem to be coding for ASFv3 - v4 will trigger your receive callback for any incoming bytes, not only once when your buffer is full (and you have received every 99 characters).
That means that io_read will most probably never return 99 (because it was only a partial read of your message) and you will most probably never send anything back.
Note the docs say (Scroll down to "different read function behavior..."):
In ASFv4 a data reception type callback in a driver with a ring buffer is triggered for every received data.
The UART apparently is a driver with a ring buffer.
You need to repeatedly call io_read and sum up the number of received bytes until you have got 99. Only then proceed. The ASF docs have an example for that. Make sure you copy code from there that fits your version.

PIC32 wrong SPI MOSI

I'm trying to develop a interface SPI and I have started with a simple configuration.
The question is that SCK seems to work fine but MOSI doesnt works.
Here is my code and my test logical tester.
#include <stdlib.h>
#include <plib.h>
// example functions prototypes
int SpiDoMasterSlaveExample(int nCycles);
void SpiInitDevice(int chn, int isMaster, int frmEn, int frmMaster);
// some definitions
#define MIN_SPI_TXFER_SIZE 8 // min number of words per transfer
#define MAX_SPI_TXFER_SIZE 512 // max number of words per transfer
// configuration settings
#pragma config FNOSC = PRIPLL, POSCMOD = HS, FPLLMUL = MUL_18, FPLLIDIV = DIV_2, FPBDIV = DIV_2, FPLLODIV = DIV_1
#pragma config FWDTEN = OFF
int main(void)
{
SYSTEMConfigPerformance(72000000L);
srand(ReadCoreTimer()); // seed the pseudo random generator
if(!SpiDoMasterSlaveExample(100))
{
return 0; // our example failed
}
return 1;
}
int SpiDoMasterSlaveExample(int nCycles)
{
int fail=0; // overall result
SpiInitDevice(1, 1, 1, 1); // initialize the SPI channel 1 as master, frame master
SpiInitDevice(2, 0, 1, 0); // initialize the SPI channel 2 as slave, frame slave
while(nCycles-- && !fail)
{
unsigned int txferSize;
unsigned short* pTxBuff;
unsigned short* pRxBuff;
txferSize=MIN_SPI_TXFER_SIZE+rand()%(MAX_SPI_TXFER_SIZE-MIN_SPI_TXFER_SIZE+1); // get a random transfer size
pTxBuff=(unsigned short*)malloc(txferSize*sizeof(short));
pRxBuff=(unsigned short*)malloc(txferSize*sizeof(short)); // we'll transfer 16 bits words
if(pTxBuff && pRxBuff)
{
unsigned short* pSrc=pTxBuff;
unsigned short* pDst=pRxBuff;
int ix;
int rdData;
for(ix=0; ix<txferSize; ix++)
{
pTxBuff[ix]='A'; // fill buffer with some random data
}
ix=txferSize+1; // transfer one extra word to give the slave the possibility to reply back the last sent word
while(ix--)
{
SpiChnPutC(1, *pSrc++); // send data on the master channel, SPI1
rdData=SpiChnGetC(1); // get the received data
if(ix!=txferSize)
{ // skip the first received character, it's garbage
*pDst++=rdData; // store the received data
}
rdData=SpiChnGetC(2); // receive data on the slave channel, SPI2
SpiChnPutC(2, rdData); // relay back data
}
// now let's check that the data was received ok
pSrc=pTxBuff;
pDst=pRxBuff;
for(ix=0; ix<txferSize; ix++)
{
if(*pDst++!=*pSrc++)
{
fail=1; // data mismatch
break;
}
}
}
else
{ // memory allocation failed
fail=1;
}
free(pRxBuff);
free(pTxBuff); // free the allocated buffers
}
return !fail;
}
void SpiInitDevice(int chn, int isMaster, int frmEn, int frmMaster)
{
unsigned int config=SPI_CON_MODE16|SPI_CON_SMP|SPI_CON_ON; // SPI configuration word
if(isMaster)
{
config|=SPI_CON_MSTEN;
}
if(frmEn)
{
config|=SPI_CON_FRMEN;
if(!frmMaster)
{
config|=SPI_CON_FRMSYNC;
}
}
SpiChnOpen(chn, config, 4); // divide fpb by 4, configure the I/O ports. Not using SS in this example
}
Sorry, I can't post the logical analyser image for my reputation points.
I'm trying to send "A" all time (fill buffer transmit). That's send data to SPI1.
I'm reading SPI1 from my Microchip Expansion Board I/O where SPI1 is in pins 41 and 43 (41 SCK and 43 SDO).
In SPI2, pin 23 and 25, obviously I have not any traffic.
Does anyone have idea of this error?
Thanks a lot
The PIC32MX series has mapable input and output pins for some peripherals, including the SPI. This means, that MOSI and MISO can be mapped to different pins, depending on your specific needs.
You need to specify this in code before you start using the SPI, otherwise, the PIC won't know which pins to use.
The following is just an example of how to setup the pins (peripheral pin select). You need to look in your PIC's datasheet for the mappings. The first parameter in the calls is the table index from the datasheet.
/* inputs */
PPSInput(2, SDI1, RPF2); // F2, MEMORY MISO -> SPI1SDI
PPSInput(2, SDI2, RPG7); // G7, ZB MISO -> SPI2SDI
/* outputs */
PPSOutput(4, RPF3, SDO1); // F3, MEMORY MOSI -> SPI1SDO
PPSOutput(1, RPG8, SDO2); // G8, ZB MOSI -> SPI2SDO
As described before, check your peripheral pin select. Additional you must set your port direction to Output (PDx-Register). MISO must be set to an Input.

AVR Hyperterminal not displaying sensor values

I need to read values form a distance sensor in volts. The sensor sends the voltages binary values to the MUC (Atmega8) and then the atmega8 communicates to my pc using USART with and RS232 cable. The readings displayed on the PC are weird random characters. I don't understand what am I doing wrong.
Here is my code
//USART communicating with Atmega8
#include <avr/io.h>
#include <inttypes.h>
#include <util/delay.h>
#include <string.h>
//1MHZ Baud 9600
#define F_CPU 1000000
char *Bestbelieve ="t \r\n";
void InitADC()
{
ADMUX=(0<<REFS1)|(1<<REFS1); // For Aref=internal;
ADCSRA=(1<<ADEN)|(0<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); //Prescalar div factor =8
}
uint16_t ReadADC()
{
ADMUX=0x05;
//Start Single conversion
ADCSRA|=(1<<ADSC);
//Wait for conversion to complete
while(!(ADCSRA & (1<<ADIF)));
//Clear ADIF by writing one to it
//Note you may be wondering why we have write one to clear it
//This is standard way of clearing bits in io as said in datasheets.
//The code writes '1' but it result in setting bit to '0' !!!
ADCSRA|=(1<<ADIF);
return(ADC);
}
void Wait()
{
uint8_t i;
for(i=0;i<20;i++)
_delay_loop_2(0);
}
char USARTReadChar()
{
//Wait until a data is available
while(!(UCSRA & (1<<RXC)))
{
//Do nothing
}
//Now USART has got data from host
//and is available is buffer
return UDR;
}
void USARTWriteChar(char* data)
{
//Wait until the transmitter is ready
while(*data)
{ while(!(UCSRA & (1<<UDRE)))
{
//Do nothing
}
//Now write the data to USART buffer
UDR=*data;
data++;
}}
void USARTInit(uint16_t ubrr_value)
{
UBRRL = 12;
UBRRH = 0;
UCSRC=(1<<URSEL)|(3<<UCSZ0);
UCSRB=(1<<RXEN)|(1<<TXEN);
UCSRA=(1<<U2X);
}
int main()
{
uint16_t adc_result;
//Initialize ADC
InitADC();
USARTInit(12); //UBRR = 12
//Loop forever
while(1)
{
adc_result=ReadADC(); // Read Analog value from channel-0
char *result[15];
sprintf(result,"%d",adc_result);
Wait();
USARTWriteChar(adc_result);
/* The code continuously has t outputted and skipped lines.
*/
}
}
You are using sprintf to format your data into result. However, you then use USARTWriteChar on your binary value adc_result.
You need to print out result instead, presumably with a loop over the characters calling USARTWriteChar.

How to read and write GPIO values with inb() and outb()

I have an atom board with a Fintek F75111 GPIO. I have info from the manufacturer that the SMbus address to access the chip is 06EH.
I am trying to read and write values to the GPIO in Linux. I have a sample program from manufacturer written for Windows that looks like this.
#include “math.h”
#include “stdio.h”
#include “dos.h”
void main(void){
int SMB_PORT_AD = 0x400;
int SMB_DEVICE_ADD = 0x6E;
/*75111R’s Add=6eh */
//programming DIO as output //0:input 1:Output
/* Index 10, GPIO1x Output pin control */
SMB_Byte_WRITE(SMB_PORT_AD,SMB_DEVICE_ADD,0x10,0xff); delay(10);
//programming DIO default LOW
/* Index 11, GPIO1x Output Data value */
SMB_Byte_WRITE(SMB_PORT_AD,SMB_DEVICE_ADD,0x11,0x00); delay(10);
}
unsigned char SMB_Byte_READ (int SMPORT, int DeviceID, int REG_INDEX)
{
unsigned char SMB_R;
outportb(SMPORT+02, 0x00); /* clear */
outportb(SMPORT+00, 0xff); /* clear */
delay(10);
outportb(SMPORT+04, DeviceID+1); /* clear */
outportb(SMPORT+03, REG_INDEX); /* clear */
outportb(SMPORT+02, 0x48); /* read_byte */
delay(10);
SMB_R= inportb(SMPORT+05);
return SMB_R;
}
void SMB_Byte_WRITE(int SMPORT, int DeviceID, int REG_INDEX, int REG_DATA)
{
outportb(SMPORT+02, 0x00); /* clear */
outportb(SMPORT+00, 0xff); /* clear */
delay(10);
outportb(SMPORT+04, DeviceID); /* clear */
outportb(SMPORT+03, REG_INDEX); /* clear */
outportb(SMPORT+05, REG_DATA); /* read_byte */
outportb(SMPORT+02, 0x48); /* read_byte */
delay(10);
}
I have tried to translate this to Linux compatible functions inb() and outb() and this is what I got.
#include <stdio.h>
#include <sys/io.h>
unsigned int gpio_read(int PORT, int DEVICE, int REG_INDEX){
unsigned int RESPONSE;
outb(0x00, PORT+02);
outb(0xff, PORT+00);
usleep(100);
outb(DEVICE+1, PORT+04);
outb(REG_INDEX, PORT+03);
outb(0x48, PORT+02);
usleep(100);
RESPONSE = inb(PORT+05);
return RESPONSE;
}
unsigned int gpio_write(int PORT, int DEVICE, int REG_INDEX, int REG_DATA){
outb(0x00, PORT+02);
outb(0xff, PORT+00);
usleep(100);
outb(DEVICE, PORT+04);
outb(REG_INDEX, PORT+03);
outb(DATA, PORT+05);
outb(0x48, PORT+02);
usleep(100);
}
void main() {
int PORT = 0x400;
int DEVICE = 0x6E;
unsigned int RESPONSE;
// Ask access to port from kernel
ioperm(0x400, 100, 1);
// GPIO1x set to input (0xff is output)
gpio_write(PORT, DEVICE, 0x10, 0x00);
RESPONSE = gpio_read(PORT, DEVICE, 1);
printf("\n %u \n", RESPONSE);
}
GPIO1X index 0x10 is used to set if the 8 GPIO ports that are connected to GPIO1x are output ports or input ports.
Output values for GPIOs are set using the index 0x11, and if the ports work as input ports then index 0x12 is used for reading input values.
The problem is that I do not know if this is correct or how to read the values (why the read function outputs something before reading?!?)
When I run:
RESPONSE = gpio_read(PORT, DEVICE, X);
Changing X with values from 1..9 I get this as output: 0 8 8 0 0 0 0 0 0
The number 8 confuses me...
Instead of writing directly to the SMBus port, I'd rather use the i2c libraries. I2C (and SMBUS) use two Port Pins, one for the clock and one for the data. The data is trasmitted and received at the clock edges (synchronous), Reading the code, I cannot see clearly which of them (clock or data) is being accessed and when.
To get started I'd use i2ctools as a start point (check this site: http://elinux.org/Interfacing_with_I2C_Devices). This tool helps you to find devices connected to the I2C bus to your microprocessor and also perform basic commmunication.
Hope it helps...

Reading Virtual Serial Port with MicroC for 8051

I have a problem , please help me.
for about a project homework ı need read from virtual serial port with microC and send this info to AT89C52 microconttoller..
This is my source code:
int uart_rd;
void main() {
P1=0X00;
UART1_Init(9600);
delay_ms(100);
while(1)
{
if(UART1_Data_Ready()){
uart_rd=UART1_read();
if(uart_rd=='1')
{P1=0X01; delay_ms(1500); P1=0X00; }
if(uart_rd=='2')
{P1=0X02; delay_ms(1500); P1=0X00; }
}
}
}
BUT I cant get info from the port. Where is the mistake.Please help me...
You are defining your UART receive variable (uart_rd) as an int, which is a 2 byte variable. I would expect UART1_read() to return a single byte (char).
I am not familiar with your particular setup or debugging/troubleshooting options, but you might try writing some code to assist in debugging your issue. The following example may be useful. It does assume that LEDs are connected to both port 1 and port 2, so some adjustment may be necessary.
char uart_rd;
void main()
{
UART1_Init(9600); // Initialize UART at 9600 bps
delay_ms(100); // Wait for UART to stabilize
while(1)
{
if(UART1_Data_Ready())
{
P2 = 0xFF; // Turn ON PORT2 LEDs upon data ready
uart_rd = UART1_read(); // Receive data
P1 = uart_rd; // Display data on port 1 LEDs
UART1_write(uart_rd); // Transmit same data back
delay_ms(1500); // Brief delay
P1 = 0x00; // Turn OFF port 1 LEDs
P2 = 0x00; // Turn OFF port 2 LEDs
}
}
}

Resources