I am trying to design a GPS car tracker with a SIM808 module using a STM32F103RET6 header board and I want to get the location link messaged to my phone by sending an SMS to the module. Right now my code works but only when I reset the board after sending each SMS. I attached my code can you figure out what is the problem?
main code :
#include <stm32f10x.h>
#include "usart.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
char S=0x1A;
#define Enter usart_sendchar('\n');
#define CR usart_sendchar('\r');
#define GIM usart_sendchar('"');
#define SUB usart_sendchar(S);
#include "stm32f10x.h"
#include <string.h>
char get_Enter = 0;
uint8_t ch;
char str1[300];
char str2[100];
int i=0;
char flag=0;
char str_tmp[20];
char str_tmp2[20];
char* p;
volatile uint32_t msTicks;
//calling all the functions
void Send_SMS(char *text);
void CMTI(void);
void wait_to_get(char ch);
void del_All_SMS(void);
void CMGF_1(void);
void Delay (uint32_t Time);
void CMGR (void);
void CGNSPWR_1(void);
void CGNSINF(void);
void interrupt_activation(void);
void CGNSINF_C(void);
void AT(void);
void Delay (uint32_t dlyTicks);
void SysTick_Handler(void);
// the interrupt handler for the systick module
void SysTick_Handler(void) {
msTicks++;
}
void Delay (uint32_t dlyTicks) {
uint32_t curTicks;
curTicks = msTicks;
while ((msTicks - curTicks)< dlyTicks);
}
void Send_SMS(char *text)
{
CMGF_1();
Delay(500);
str_tmp[0]='\0';
Delay(100);
strcpy(str_tmp,"AT+CMGS=");
Delay(500);
usart_sendstring(str_tmp);
GIM
str_tmp[0]='\0';
Delay(100);
strcpy(str_tmp,"+98905xxxxxxx");
Delay(500);
usart_sendstring(str_tmp);
GIM
Enter
CR
Delay(500);
usart_sendstring(text);
Enter
CR
str_tmp[0]='\0';
Delay(500);
SUB
Delay(100);
del_All_SMS();
}
void USART1_IRQHandler(void) {
ch = USART1->DR & 0xFF;
if (ch == '\n'){ // 13 enter
get_Enter =1;
}
else{
str1[i]= ch;
i++;
}
}
void CMGF_1(void)
{
str_tmp[0]='\0';
Delay(100);
strcpy(str_tmp,"AT+CMGF=1");
Delay(500);
usart_sendstring(str_tmp);
Enter
CR
}
void del_All_SMS(void)
{
str_tmp[0]='\0';
Delay(100);
strcpy(str_tmp,"AT+CMGD=1,4");
Delay(500);
usart_sendstring(str_tmp);
Enter
CR
}
void CMGR(void)
{
str_tmp[0]='\0';
Delay(100);
strcpy(str_tmp,"AT+CMGR=1");
Delay(500);
usart_sendstring(str_tmp);
Enter
CR
}
void CGNSINF(void)
{
str_tmp[0]='\0';
Delay(100);
strcpy(str_tmp,"AT+CGNSINF");
Delay(500);
usart_sendstring(str_tmp);
Enter
CR
}
void CGNSPWR_1(void)
{
str_tmp[0]='\0';
Delay(100);
strcpy(str_tmp,"AT+CGNSPWR=1");
Delay(500);
usart_sendstring(str_tmp);
Enter
CR
}
void AT(void)
{
str_tmp[0]='\0';
Delay(100);
strcpy(str_tmp,"AT");
Delay(500);
usart_sendstring(str_tmp);
Enter
CR
}
int main()
{
SystemInit();
SysTick_Config(SystemCoreClock/1000); // setup systick timer for 1ms interrupts
usart_init();
AT();
p=NULL;
check:AT();
Delay(2000);
p=strstr(str1,"OK");
if(p==NULL) goto check;
CMGF_1();
Delay(500);
CGNSPWR_1();
Delay(500);
del_All_SMS();
Delay(500);
RCC->APB2ENR |= (1<<3);
GPIOB->CRL &= ~0xF;
GPIOB->CRL |= 0x3;
while (1)
{
if (get_Enter ==1)
{
if (flag==0){
////waiting for +CMTI: from sim800
do
{
p=strstr(str1,"+CMTI:");
}
while(p==NULL);
Delay(1000);
// sending AT+CMGR=1 command
if (p!=NULL)
{
CMGR();
Delay(350);
flag=1;
}
}
if (flag==1) {
p=strstr(str1,"+CMGR");
if (p){
p=strstr(str1,"loc");
if (p!=NULL)
{
CGNSINF();
Delay(300);
}
else if (p==NULL)
{
del_All_SMS();
memset(str1, 0, 300);
flag=0;
}
p=strstr(str1,"+CGNSINF:");
if (p)
{
float a[5];
char str2[80];
const char s[2] = ",";
char *token;
// getting the lattitude and longitude
token = strtok(p, s);
for (int i=0;i<5;i++){
sprintf( str2," %s\n", token );
a[i]=atof(str2);
token = strtok(NULL, s);
}
sprintf(str2,"https://maps.google.com/?q=%.6f,%.6f",a[3],a[4]);
Send_SMS(str2);
p=NULL;
del_All_SMS();
flag=0;
memset(str1, 0, 300);
}
}
}
}
}
}
usart code :
#include "stm32f10x.h"
#include "usart.h"
char str[200];
char data;
//// initialize usart
void usart_init(void)
{
RCC->APB2ENR |= ( 1UL << 0); /* enable clock Alternate Function */
AFIO->MAPR &= ~( 1UL << 2); /* clear USART1 remap */
RCC->APB2ENR |= ( 1UL << 2); /* enable GPIOA clock */
GPIOA->CRH &= ~(0xFFUL << 4); /* clear PA9, PA10 */
GPIOA->CRH |= (0x0BUL << 4); /* USART1 Tx (PA9) output push-pull */
GPIOA->CRH |= (0x04UL << 8); /* USART1 Rx (PA10) input floating */
RCC->APB2ENR |= ( 1UL << 14); /* enable USART#1 clock */
USART1->BRR=0x1D4C; // 9600 #72MHz
// USART1->BRR = 0x0271; /* 115200 baud # PCLK2 72MHz */
USART1->CR1 = (( 1UL << 2) | /* enable RX */
( 1UL << 3) | /* enable TX */
( 0UL << 12) ); /* 1 start bit, 8 data bits */
USART1->CR2 = 0x0000; /* 1 stop bit */
USART1->CR3 = 0x0000; /* no flow control */
USART1->CR1 |= ( 1 << 13); /* enable USART */
USART1->CR1 |= ( 1UL << 5); // RXNE interrupt enable
NVIC_SetPriority(USART1_IRQn,5); /* Default priority group 0, can be 0(highest) - 31(lowest) */
NVIC_EnableIRQ(USART1_IRQn); /* Enable UART0 Interrupt */
}
void usart_sendchar(char data){
while(!(USART1->SR&(1<<7)));
USART1->DR=data;
}
char usart_getchar(void)
{
while (!(USART1->SR&(1<<5)));
data=USART1->DR ;
return data;
}
void usart_getstring(char *str)
{
char *temp = str;
do{
*temp = usart_getchar();
usart_sendchar (*temp) ;
} while(*(temp++) != 0x0D );
*(temp-1) = 0;
}
void usart_sendstring(char *s)
{
while (*s)
{
usart_sendchar(*s);
s++;
}
}
Related
I'm attempting to get a smartphone app to communicate with an MCU (STM32F030R8). The step I'm currently on is getting the WiFi module to talk with the MCU. I'm able use the AT firmware to configure the ESP when using an Arduino Uno/PC terminal, but want to essentially do the same via the STM board.
When I load the code to the STM and use Tera Term to send data to the STM it should be able to send AT commands to the ESP, but it isn't working. Right now I'm at a loss as to why this isn't working. I'm looking for pointers on the code that I've probably missed or other principles I've overlooked/am unaware of.
I've searched around on the internet the past couple days and haven't come up with much that helps. This is effectively the sum of my experience with C. Thanks for your help!
The hardware is set up as follows...
STM32 ESP
PA10 TX
PA9 RX
3.3V VCC
3.3V CH_PD
GND GND
UNO ESP
TX TX
RX RX
3.3V VCC
3.3V CH_PD
GND GND
The code I've frankenstein'd together is below. I'm using Keil uVision 5.
#include "stm32f0xx.h"
#include <stdio.h>
#include <string.h>
void USART1_Init(void);
void USART2_Init(void);
void USART1_Write(char ch[]);
char USART1_Read(void);
int main(void)
{
// disable the interrupt detection
__disable_irq();
RCC->AHBENR |= 0x00020000; // enable port A clock
GPIOA->MODER |= 0x00000400; // set mode for PA5
USART1_Init();
USART2_Init();
char strCommand[50];
NVIC_EnableIRQ(USART1_IRQn);
__enable_irq();
printf("\r\nInterface for ESP8266 AT commands.\r\n");
printf("Please enter the AT command: ");
gets(strCommand);
USART1_Write(strCommand);
printf("\r\n");
while (1);
}
// write data to the peripheral via USART1
void USART1_Write(char ch[])
{
// wait while the tx buffer is empty
while (!(USART1->ISR & 0x00000080));
for (int i = 0; i < strlen(ch); i++)
{
USART1->TDR = (ch[i] & 0xFF);
}
USART1->TDR = 0x0000000D;
USART1->TDR = 0x0000000A;
}
// read data from the peripheral via USART1
char USART1_Read(void)
{
// wait while the rx buffer is empty
while (USART1->ISR & 0x00000020);
return USART1->RDR;
}
// write data to the PC via USART2
int USART2_Write(int ch)
{
// wait while the tx buffer is empty
while (!(USART2->ISR & 0x00000080));
USART2->TDR = (ch & 0xFF);
return ch;
}
// read data from the PC via USART2
int USART2_Read(void)
{
// wait while the rx buffer is empty
while (!(USART2->ISR & 0x00000020));
return USART2->RDR;
}
// initialize USART1
void USART1_Init(void)
{
RCC->APB2ENR |= 0x00004000; // enable USART1 clock
GPIOA->AFR[1] |= 0x00000110; // set AF1 to PA9, PA10
GPIOA->MODER |= 0x00280000; // define GPIO modes to alternate function for PA9, PA10
USART1->BRR = 0x00000341; // set the baud rate, 9600 # 8MHz
USART1->CR1 = 0x0000002C; // enable te, re, and rx interrupt
USART1->CR1 |= 0x00000001; // enable ue
}
// initialize USART2
void USART2_Init(void)
{
RCC->APB1ENR |= 0x00020000; // enable USART2 clock
GPIOA->AFR[0] |= 0x00001100; // set AF1 to PA2, PA3
GPIOA->MODER |= 0x000000A0; // define GPIO modes to alternate function for PA2, PA3
USART2->BRR = 0x00000341; // set the baud rate, 9600 # 8MHz
USART2->CR1 = 0x0000000C; // enable te and re
USART2->CR1 |= 0x00000001; // enable ue
}
// handle the USART1 interrupt event
void USART1_IRQHandler(void)
{
char c;
if (USART1->ISR & 0x00000020)
{
c = USART1->RDR;
//GPIOA->ODR ^= 0x00000020; // toggle the PA5 state
printf("%c", c);
}
}
// implement stdin/stdout/stderr functionality
struct __FILE{int handle;};
FILE __stdin = {0};
FILE __stdout = {1};
FILE __stderr = {2};
int fgetc(FILE *f)
{
int c;
c = USART2_Read();
if (c == '\r')
{
USART2_Write(c);
c = '\n';
}
USART2_Write(c);
return c;
}
int fputc(int c, FILE *f)
{
return USART2_Write(c);
}
EDIT:
I've modified the code a bit and kept trying. When attempting to change the broadcasted network name/password (it didn't work) it now replies with the first two typed characters in the command consistently and after a moment put forth the gibberish at looks like it should have been summoned with an "AT+GMR" command. The following code is what was uploaded to the device. Any thoughts on how this could have happened? Thanks!
#include "stm32f0xx.h"
#include <stdio.h>
#include <string.h>
void USART1_Init(void);
void USART2_Init(void);
void USART1_Write(char ch[]);
char USART1_Read(void);
int main(void)
{
// disable the interrupt detection
__disable_irq();
RCC->AHBENR |= 0x00020000; // enable port A clock
GPIOA->MODER |= 0x00000400; // set mode for PA5
USART1_Init();
USART2_Init();
char strCommand[50];
NVIC_EnableIRQ(USART1_IRQn);
__enable_irq();
printf("\r\nInterface for ESP8266 AT commands.\r\n");
printf("Please enter the AT command: ");
gets(strCommand);
USART1_Write(strCommand);
printf("\r\n");
while (1);
}
// write data to the peripheral via USART1
void USART1_Write(char ch[])
{
// wait for the tx buffer to be empty
while (!(USART1->ISR & 0x00000080));
for (int i = 0; i < strlen(ch); i++)
{
USART1->TDR = (ch[i] & 0xFF);
}
// USART1->TDR = '\r';
// USART1->TDR = '\n';
}
// read data from the peripheral via USART1
char USART1_Read(void)
{
// wait while the rx buffer is empty
while (USART1->ISR & 0x00000020);
return USART1->RDR;
}
// write data to the PC via USART2
int USART2_Write(int ch)
{
// wait while the tx buffer is empty
while (!(USART2->ISR & 0x00000080));
USART2->TDR = (ch & 0xFF);
return ch;
}
// read data from the PC via USART2
int USART2_Read(void)
{
// wait while the rx buffer is empty
while (!(USART2->ISR & 0x00000020));
return USART2->RDR;
}
// initialize USART1
void USART1_Init(void)
{
RCC->APB2ENR |= 0x00004000; // enable USART1 clock
GPIOA->AFR[1] |= 0x00000110; // set AF1 to PA9, PA10
GPIOA->MODER |= 0x00280000; // define GPIO modes to alternate function for PA9, PA10
USART1->BRR = 0x00000341; // set the baud rate, 9600 # 8MHz
USART1->CR1 = 0x0000002C; // enable te, re, and rx interrupt
USART1->CR1 |= 0x00000001; // enable ue
}
// initialize USART2
void USART2_Init(void)
{
RCC->APB1ENR |= 0x00020000; // enable USART2 clock
GPIOA->AFR[0] |= 0x00001100; // set AF1 to PA2, PA3
GPIOA->MODER |= 0x000000A0; // define GPIO modes to alternate function for PA2, PA3
USART2->BRR = 0x00000341; // set the baud rate, 9600 # 8MHz
USART2->CR1 = 0x0000000C; // enable te and re
USART2->CR1 |= 0x00000001; // enable ue
}
// handle the USART1 interrupt event
void USART1_IRQHandler(void)
{
char c;
while (1)
{
if (USART1->ISR & 0x00000020)
{
c = USART1->RDR;
}
else
{
break;
}
printf("%c", c);
}
}
// implement stdin/stdout/stderr functionality
struct __FILE{int handle;};
FILE __stdin = {0};
FILE __stdout = {1};
FILE __stderr = {2};
int fgetc(FILE *f)
{
int c;
c = USART2_Read();
if (c == '\r')
{
USART2_Write(c);
c = '\n';
}
USART2_Write(c);
return c;
}
int fputc(int c, FILE *f)
{
return USART2_Write(c);
}
I was able to get the ESP to respond to the AT commands with the following code. There are sections commented out as I was simply frankensteining my way to 'working' code. I was able to change the SSID and password via a hard coded string. I simply sent it by pressing 'Enter' to get the code to proceed.
As it turns out the issue laid in sending data to the ESP (rather than receiving, which was my initial theory). Now I need to get the code to receive an uint8_t[] from the terminal, but that is a separate issue from the original question so I'll mark this as answered.
Thank you #hamboy75, #Juraj, and #KamilCuk for your help!
#include "stm32f0xx.h"
#include <stdio.h>
#include <string.h>
void USART1_Init(void);
void USART2_Init(void);
void USART1_Write(char ch[]);
char USART1_Read(void);
void USART1_Get(unsigned char *string);
void USART1_PutChar(uint8_t ch);
void USART1_Write2(uint8_t *str);
int main(void)
{
// disable the interrupt detection
__disable_irq();
RCC->AHBENR |= 0x00020000; // enable port A clock
GPIOA->MODER |= 0x00000400; // set mode for PA5
USART1_Init();
USART2_Init();
char strCommand[50];
uint8_t str[] = "AT+CWSAP_CUR=\"tempNetwork\",\"tempPassword\",1,2,1,0\r\n";
NVIC_EnableIRQ(USART1_IRQn);
__enable_irq();
printf("\r\nInterface for ESP8266 AT commands.\r\n");
printf("Please enter the AT command: ");
gets(strCommand);
//USART1_Write(strCommand);
USART1_Write2(str);
printf("\r\n");
while (1);
}
// write data to the peripheral via USART1
void USART1_Write(char ch[])
{
// wait for the tx buffer to be empty
while (!(USART1->ISR & 0x00000080));
for (int i = 0; i < strlen(ch); i++)
{
//USART1->TDR = (ch[i] & 0xFF);
}
//USART1->TDR = '\r';
//USART1->TDR = '\n';
USART1->TDR = ('T' & 0xFF);
USART1->TDR = ('T' & 0xFF);
USART1->TDR = '\r';
USART1->TDR = '\n';
}
// write a string via USART1
void USART1_Write2(uint8_t *str)
{
while (*str != 0)
{
USART1_PutChar(*str);
str++;
}
}
// write one character via USART1
void USART1_PutChar(uint8_t ch)
{
while (!(USART1->ISR & 0x00000080));
USART1->TDR = ch;
}
// read data from the peripheral via USART1
char USART1_Read(void)
{
// wait while the rx buffer is empty
while (USART1->ISR & 0x00000020);
return USART1->RDR;
}
// write data to the PC via USART2
int USART2_Write(int ch)
{
// wait while the tx buffer is empty
while (!(USART2->ISR & 0x00000080));
USART2->TDR = (ch & 0xFF);
return ch;
}
// read data from the PC via USART2
int USART2_Read(void)
{
// wait while the rx buffer is empty
while (!(USART2->ISR & 0x00000020));
return USART2->RDR;
}
// initialize USART1
void USART1_Init(void)
{
RCC->APB2ENR |= 0x00004000; // enable USART1 clock
GPIOA->AFR[1] |= 0x00000110; // set AF1 to PA9, PA10
GPIOA->MODER |= 0x00280000; // define GPIO modes to alternate function for PA9, PA10
USART1->BRR = 0x00000341; // set the baud rate, 9600 # 8MHz
USART1->CR1 = 0x0000002C; // enable te, re, and rx interrupt
USART1->CR1 |= 0x00000001; // enable ue
}
// initialize USART2
void USART2_Init(void)
{
RCC->APB1ENR |= 0x00020000; // enable USART2 clock
GPIOA->AFR[0] |= 0x00001100; // set AF1 to PA2, PA3
GPIOA->MODER |= 0x000000A0; // define GPIO modes to alternate function for PA2, PA3
USART2->BRR = 0x00000341; // set the baud rate, 9600 # 8MHz
USART2->CR1 = 0x0000000C; // enable te and re
USART2->CR1 |= 0x00000001; // enable ue
}
// handle the USART1 interrupt event
void USART1_IRQHandler(void)
{
char c;
while (1)
{
if (USART1->ISR & 0x00000020)
{
c = USART1->RDR;
printf("%c", c);
}
else
{
break;
}
}
}
// implement stdin/stdout/stderr functionality
struct __FILE{int handle;};
FILE __stdin = {0};
FILE __stdout = {1};
FILE __stderr = {2};
int fgetc(FILE *f)
{
int c;
c = USART2_Read();
if (c == '\r')
{
USART2_Write(c);
c = '\n';
}
USART2_Write(c);
return c;
}
int fputc(int c, FILE *f)
{
return USART2_Write(c);
}
My STM and Raspberry do successfully comunicate via USART. Rx and Tx word fine, until the Raspberry stops to send. Then the STM listens and listens for new chars. The code cycle is stuck until a char is received.
I want to implement a timeout interrupt.
This is what I found.
STM32H7 documentation (page 21)
Unfortunatelly it's for the wrong board. The receive timeout cannot be found in the reference manual for the STMF4. So I guess this functionality is not given for my board?
I am using Keil µVision V5.28.0.0 and standard peripherals.
Here is a code snippet
#include "main.h"
#include <stdio.h>
USART_InitTypeDef USART_InitStruct;
volatile uint32_t msTicks=0;
void USART_Initialise(void);
int USART_putchar(char ch);
void USART_puts(char str[]);
char USART_receive(void);
void Delay (int ms);
int main(void)
{
char buffer[20];
string test = "test";
USART_Initialise();
while (1)
{
char mode = USART_receive();
if (mode == '+')
{
sprintf(buffer, "%.2lf",test);
USART_puts(buffer);
}
Delay(300);
}//while
}//main
void USART_Initialise(void)
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
RCC_APB1PeriphClockCmd (RCC_APB1Periph_USART3, ENABLE);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_USART3);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_USART3);
GPIO_StructInit(&GPIO_InitStruct);
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11; //GPIO Pin 10 & 11
GPIO_Init(GPIOC, &GPIO_InitStruct);
USART_StructInit(&USART_InitStruct);
USART_InitStruct.USART_BaudRate=9600;
USART_InitStruct.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
USART_InitStruct.USART_Mode=USART_Mode_Rx | USART_Mode_Tx;
USART_InitStruct.USART_Parity=USART_Parity_No;
USART_InitStruct.USART_StopBits=USART_StopBits_1;
USART_InitStruct.USART_WordLength=USART_WordLength_8b;
USART_Init(USART3, &USART_InitStruct);
USART_Cmd(USART3, ENABLE);
}
int USART_putchar(char ch)
{
USART_SendData(USART3, (uint8_t) ch);
while (USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET)
{}
return ch;
}
void USART_puts(char str[])
{
while (*str != 0)
{
USART_putchar(*str);
str++;
}
}
char USART_receive(void)
{
while (USART_GetFlagStatus(USART3, USART_FLAG_RXNE) == RESET){};
char rxd_receive = USART_ReceiveData(USART3);
return rxd_receive;
}
void SysTick_Handler(void) //für ISR kein Prototyp erforderlich
{
msTicks--;
}
void Delay (int ms)
{
msTicks = ms;
while (msTicks>0);
}
Change your receive function into:
int USART_receive(void)
{
if (USART_GetFlagStatus(USART3, USART_FLAG_RXNE) == RESET)
{
return EOF;
}
return USART_ReceiveData(USART3);
}
Then you can decide what to do on receiving a character in the upper layer.
You might also put the timeout in the function. Then it will return EOF if the timeout happens. Since you say the UART does not include an own timeout functionality, you need to use one of the timers.
I am using LPC2148 with SIM800L on UART1 using interrupt. When I use memset(buff, 0 , sizeof(buff)); in while(1) at first the program works fine but when while(1) loop runs again it prints error over and over but when I comment the memset(buff, 0, sizeof(buff)); it works fine.
So why it is not receiving the data on using memset function?
#include <lpc214x.h>
#include <stdio.h>
#include <string.h>
__irq void uart1_interrupt(void);
void init_uart1(void); //////initialize uart1
void uart1_write(char data); //////send char on uart1
void uart1_send_string(char *str);//////send string on uart1
void Uart0_string(char *str); //////send string on uart0
void U0write(char data); //////send
char on uart0
void init_uart0(void); //////initialize uart0
void pll_init(void);
void timer_init(void);
void delay_ms(unsigned int ms);
//void clear_data(); /////clear buffer
char buff[160];
//char sms_receive[60];
int i, a = 0;
int main(void)
{
pll_init();
timer_init();
init_uart0();
//init_uart1();
VICVectAddr0 = (unsigned) uart1_interrupt; /////attach interrupt routine
VICVectCntl0 = (1<<5)|7; ////enable uart irq slot for uart1
VICIntEnable |= (1<<7); ////enable uart1 interrupt
VICIntSelect = 0x00000000;
init_uart1();
Uart0_string("gsm test\r\n");
delay_ms(3000);
while(1)
{
uart1_send_string("AT\r\n");
delay_ms(400);
if(strstr(buff,"OK"))
{
Uart0_string(buff);
}
else
{
Uart0_string("ERROR ");
}
delay_ms(3000);
uart1_send_string("AT+CNMI=?\r\n");
delay_ms(400);
if(strstr(buff,"+CNMI"))
{
Uart0_string(buff);
}
else
{
Uart0_string("ERROR ");
}
delay_ms(3000);
//clear_data();
memset(buff, 0 , sizeof(buff));
}
}
/*void clear_data()
{
for(i = 0; i<=sizeof(buff); i++)
{
buff[i] = 0;
}
}*/
__irq void uart1_interrupt(void)
{
buff[a] = U1RBR;
a++;
VICVectAddr = 0x00;
}
void init_uart1(void)
{
PINSEL0 = PINSEL0 | 0x00050000; ////UART1 pin selection
U1LCR = 0x83; ////8 bit, no parity, 1 stop bit, DLAB - 1
U1DLL = 0x56; ////86 in decimal
U1DLM = 0x00;
U1FDR = 0xF2;
U1LCR &= 0x0f; /////setting DLAB bit to 0
U1IER = 0x01; ////enable interrupt
}
void uart1_write(char data)
{
U1IER = 0x00;
while(!(U1LSR &(1<<5))); ////U1LSR contains THRE status bit, wait while THR is empty
U1THR = data;
U1IER = 0x01;
}
void uart1_send_string(char *str)
{
U1IER = 0x00;
while(*str != '\0')
{
uart1_write(*str++);
}
U1IER = 0x01;
}
/*char uart1_receive()
{
while(!(U1LSR & (1<<0)));
return U1RBR;
}*/
void init_uart0()
{
PINSEL0 = 0x00000005; ////selects TxD P0.0 and RxD P0.1
U0LCR = 0x83; ////8 bit, no parity 1 stop bit, DLAB = 1
U0DLL = 0x56; //// 86 in decimal
U0DLM = 0x00;
U0FDR = 0xF2; ////MULVAL and DIVADDVAL values
U0LCR &= 0x0F;
}
void U0write(char data)
{
while(!(U0LSR & (1<<5))); ///////wait till THR is not empty
U0THR = data; /////// write data to Transmit in U0THR
}
void Uart0_string(char *str)
{
while(*str != '\0')
{
U0write(*str++);
}
}
void pll_init(void)
{
PLL0CON = 0x01; /////enable PLL////
PLL0CFG = 0x24; /////configure PLL/////
PLL0FEED = 0xAA; //////feed sequence/////
PLL0FEED = 0x55; //////feed sequence/////
while(!(PLL0STAT & 0x00000400)); ///is locked////
PLL0CON = 0x03; ////connect PLL////
PLL0FEED = 0xAA;
PLL0FEED = 0x55;
//VPBDIV = 0x01; /////// PCLK = CCLK = 60MHz
VPBDIV = 0x00; /////// PCLK = 60/4 = 15MHz
}
void timer_init(void)
{
//T0TCR = 0x00;
T0CTCR = 0x0; ////selection of timer mode with every rising pclk edge
T0PR = 14999; ////prescale register value will generate 1 ms at 60MHz
T0TCR = 0x02; ////reset the timer counter and prescale couter
}
void delay_ms(unsigned int ms)
{
//T0TC = 0x00000000;
T0TCR = 0x02; /////reset timer. Timer should be reset
T0TCR = 0x01; /////enable timer to generate delay
T0MR0 = ms;
while(T0TC < T0MR0); /////wait until Timer counter register reaches desired delay
T0TCR = 0x00; /////disable timer
}
output when using memset(buff, 0, sizeof(buff))
gsm test
AT
OK
AT
OK
AT+CNMI=?
+CNMI: (0-3),(0-3),(0,2),(0,1),(0,1)
OK
ERROR ERROR ERROR ERROR
output when not using memset(buff, 0 , sizeof(buff)). I want to achive this output using memset(buff, 0 , sizeof(buff))
gsm test
AT
OK
AT
OK
AT+CNMI=?
+CNMI: (0-3),(0-3),(0,2),(0,1),(0,1)
OK
AT
OK
AT+CNMI=?
+CNMI: (0-3),(0-3),(0,2),(0,1),(0,1)
OK
AT
OK
AT
OK
AT+CNMI=?
+CNMI: (0-3),(0-3),(0,2),(0,1),(0,1)
OK
AT
OK
AT+CNMI=?
+CNMI: (0-3),(0-3),(0,2),(0,1),(0,1)
OK
AT
OK
AT+CNMI=?
+CNMI: (0-3),(0-3),(0,2),(0,1),(0,1)
OK
AT
OK
AT+CNMI=?
+CNMI: (0-3),(0-3),(0,2),(0,1),(0,1)
OK
AT
OK
a is reset only once at the start. The interrupt increments a on every character. When your main loop repeats, the ISR (interrupt service routine) will increment it further, finally overwriting the memory after buf.
That's why without memset() you get ever repeating the same result. The contents of buf is always checked from its beginning, but the received answers are stored one after the other.
Reset a on every entry in the loop, that should help.
However, writing (and/or reading) to the same variable from more than one thread is calling for disaster. Look for some lessons about multi-threaded programming. Yes, using interrupts is programming with multiple threads.
The while(1) loop in the main function does not make any input to char buff[160]. That is done only in the interrupt handler. So when you use memset to fill the buffer, it then begins with the string terminator character '\0' and the statements
if(strstr(buff,"OK"))
and
if(strstr(buff,"+CNMI"))
are false – NULL means no match was found – and so the error messages are output.
Note too that in the interrupt handler __irq void uart1_interrupt(void) you have
buff[a] = U1RBR;
a++;
but nowhere is a limited or reset or wrapped to prevent buffer overrun. So there is a disaster waiting to happen.
I have problem when want to determine the address for each LED in dot-matrix 8x8 74HC595, im trying to light on only 1 LED specifically with the address. i have tried many tutorial and documentation but still no luck to light on only 1 LED with spesific location.
this is my circuit design :
https://www.sunfounder.com/learn/Super_Kit_V2_for_RaspberryPi/lesson-12-driving-dot-matrix-by-74hc595-super-kit-for-raspberrypi.html
my code with C:
#include <wiringPi.h>
#include <stdio.h>
#define SDI 0 //serial data input
#define RCLK 1 //memory clock input
#define SRCLK 2 //shift register clock input
unsigned char LED[8] ={0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
void pulse(int pin)
{
digitalWrite(pin, 0);
digitalWrite(pin, 1);
}
void ShiftOUT(unsigned char byte)
{
int i;
for(i=0;i<8;i++)
{
// char a = byte & (0x80 >> i)) > 0;
digitalWrite(SDI, (( byte & (0x80 >> i)) > 0));
printf("%d", (( byte >> i > 0)));
pulse(SRCLK);
}
printf("\n","==================");
}
void init(void)
{
pinMode(SDI, OUTPUT);
pinMode(RCLK, OUTPUT);
pinMode(SRCLK, OUTPUT);
digitalWrite(SDI, 0);
digitalWrite(RCLK, 0);
digitalWrite(SRCLK, 0);
}
int main(void)
{
int i;
if(wiringPiSetup() == -1)
{
printf("setup wiringPi failed !");
return 1;
}
init();
while(1)
{
for(i=0;i<8;i++)
{
ShiftOUT(LED[i]);
pulse(RCLK);
// printf("=======pull latch========");
// printf("\n");
delay(150);
}
delay(500);
}
return 0;
}
This code i tried will light on 1 row,i want to light on 1 LED with spesific location
Here is the link i use for simulation to addressing the LED : https://www.riyas.org/2013/12/online-led-matrix-font-generator-with.html
Any help?Thank you
When the timer match MR0, run the interrupt service routine At the end of the interrupt service routine. I don't return from service routine to main program. Why does my program not return from service routine?
See answer below for complete code
the code is /* Timer.h */
#include "LPC214x.h"
#include "main.h"
#define VIC_EN 5
#define VIC_TIMER0 4
#define MR0 0
void timer_init(void);
void timer_isr(void);
/* Timer.c */
volatile uint8_t flag;
void timer_init()
{
//disable and reset timer counters
T0TCR = BV(1);
//use T0 as TIMER:
T0CTCR = 0x00;
//set prescalar
T0PR = 15000000-1;
//setup MR0 for 5 sec
T0MR0 = 4; //4+1
//enable intr on MR0, reset
T0MCR |= BV(0) | BV(1);
//enable T0 intr in VIC
VICVectAddr1 = (uint32_t)timer_isr;
VICVectCntl1 = BV(VIC_TIMER0) | VIC_EN;
VICIntSelect &= ~BV(VIC_TIMER0);
VICIntEnable |= BV(VIC_TIMER0);
//enable timer counter
T0TCR = BV(0);
}
void timer_isr()
{
flag=1;
//clear intr in TIMER regrs
T0IR |= BV(0);
//clear intr in VIC
VICVectAddr = 0x00000000;
}
/* Main.c*/
int main (void)
{
int cnt=0;
char str[32];
timer_init();
lcd_init();
lcd_putstring(LCD_LINE1," *TIMER* ");
_delay_ms(1000);
str_printf(str,"Count:%d",cnt);
//lcd_putstring(LCD_LINE2,str);
while(1)
{
while(flag==0);
flag = 0;
cnt++;
str_printf(str,"Count:%d",cnt);
lcd_putstring(LCD_LINE2,str);
}
return 0;
}