Hi. I'm trying to send a string from the ESP8266-01S module to PIC16F887 through UART and the string received by the PIC will be used to turn a LED on and off. The ESP has been programmed to send the string "LED1_ON" and "LED_OFF" at an interval of 2s. The PIC will turn on the LED when it receives "LED1_ON" and turn off the LED when it receives "LED1_OFF". So, the LED connected to the output pin of the PIC should be on and off every 2s. To check the string being received, I also print the string on the LCD. However, only letter 'N' and 'F' being printed on the LCD every 2s. I think the string is not being received correctly and that's causing the LED being off all the time.
I've programmed the ESP using Arduino IDE and programmed the PIC using MPLABX IDE. I don't know if it's the code on ESP side or the code on the PIC side that is causing the problem.
Code for ESP8266:
void setup() {
Serial.begin(9600); // Initialize the Serial interface with baud rate of 9600
}
void loop() {
Serial.print("LED1_ON");
delay(2000);
Serial.print("LED1_OFF");
delay(2000);
}
Code for PIC:
#pragma config CONFIG1 = 0xECD4
#pragma config CONFIG2 = 0xFFFF
#define _XTAL_FREQ 8000000
/* LCD module connections */
#define LCD_RS RD0
#define LCD_EN RD1
#define LCD_D4 RD2
#define LCD_D5 RD3
#define LCD_D6 RD4
#define LCD_D7 RD5
#define LCD_RS_DIR TRISD0
#define LCD_EN_DIR TRISD1
#define LCD_D4_DIR TRISD2
#define LCD_D5_DIR TRISD3
#define LCD_D6_DIR TRISD4
#define LCD_D7_DIR TRISD5
#include <xc.h>
#include <stdio.h> // for sprintf
#include <stdint.h> // include stdint header
#include "UART.h" // UART library
#include "LCD_LIB.h" // LCD library
char UARTData[];
void __interrupt() ISR(){
if(RCIF == 1){
char i = 0;
char c;
while (UART_Data_Ready()){
UARTData[i] = UART_GetC();
i++;
LCD_Goto(i,1);
LCD_PutC(UARTData[i-1]);
if (UARTData[i] == '\0')
break;
}
if ( !(strcmp(UARTData, "LED1_ON")) )
RA0 = 1;
else
RA0 = 0;
RCIF = 0;
}
}
void main(void) {
OSCCON = 0x70; // set internal oscillator to 8MHz
TRISA = 0;
ANSEL = 0;
GIE = 1; // Enable global interrupt
PEIE = 1; // Enable peripheral interrupt
RCIE = 1; // Enable UART reception interrupt
RA0 = 0;
LCD_Begin(); // initialize LCD
UART_Init(9600); // initialize UART module with 9600 baud
while(1);
return;
}
LCD library for PIC:
#pragma warning disable 520
#include <stdint.h>
#define LCD_FIRST_ROW 0x80
#define LCD_SECOND_ROW 0xC0
#define LCD_THIRD_ROW 0x94
#define LCD_FOURTH_ROW 0xD4
#define LCD_CLEAR 0x01
#define LCD_RETURN_HOME 0x02
#define LCD_ENTRY_MODE_SET 0x04
#define LCD_CURSOR_OFF 0x0C
#define LCD_UNDERLINE_ON 0x0E
#define LCD_BLINK_CURSOR_ON 0x0F
#define LCD_MOVE_CURSOR_LEFT 0x10
#define LCD_MOVE_CURSOR_RIGHT 0x14
#define LCD_TURN_ON 0x0C
#define LCD_TURN_OFF 0x08
#define LCD_SHIFT_LEFT 0x18
#define LCD_SHIFT_RIGHT 0x1E
#ifndef LCD_TYPE
#define LCD_TYPE 2 // 0=5x7, 1=5x10, 2=2 lines
#endif
__bit RS;
void LCD_Write_Nibble(uint8_t n);
void LCD_Cmd(uint8_t Command);
void LCD_Goto(uint8_t col, uint8_t row);
void LCD_PutC(char LCD_Char);
void LCD_Print(char* LCD_Str);
void LCD_Begin();
/* NOTE: The pin number for LCD_RS, LCD_D4, ... are defined in main file */
void LCD_Write_Nibble(uint8_t n)
{
LCD_RS = RS;
LCD_D4 = n & 0x01;
LCD_D5 = (n >> 1) & 0x01;
LCD_D6 = (n >> 2) & 0x01;
LCD_D7 = (n >> 3) & 0x01;
// send enable pulse
LCD_EN = 0;
__delay_us(1);
LCD_EN = 1;
__delay_us(1);
LCD_EN = 0;
__delay_us(100);
}
void LCD_Cmd(uint8_t Command)
{
RS = 0;
LCD_Write_Nibble(Command >> 4);
LCD_Write_Nibble(Command);
if((Command == LCD_CLEAR) || (Command == LCD_RETURN_HOME))
__delay_ms(2);
}
void LCD_Goto(uint8_t col, uint8_t row)
{
switch(row)
{
case 2:
LCD_Cmd(LCD_SECOND_ROW + col - 1);
break;
case 3:
LCD_Cmd(LCD_THIRD_ROW + col - 1);
break;
case 4:
LCD_Cmd(LCD_FOURTH_ROW + col - 1);
break;
default: // case 1:
LCD_Cmd(LCD_FIRST_ROW + col - 1);
}
}
void LCD_PutC(char LCD_Char)
{
RS = 1;
LCD_Write_Nibble(LCD_Char >> 4);
LCD_Write_Nibble(LCD_Char );
}
void LCD_Print(char* LCD_Str)
{
uint8_t i = 0;
RS = 1;
while(LCD_Str[i] != '\0')
{
LCD_Write_Nibble(LCD_Str[i] >> 4);
LCD_Write_Nibble(LCD_Str[i++] );
}
}
void LCD_Begin()
{
RS = 0;
LCD_RS = 0;
LCD_EN = 0;
LCD_D4 = 0;
LCD_D5 = 0;
LCD_D6 = 0;
LCD_D7 = 0;
LCD_RS_DIR = 0;
LCD_EN_DIR = 0;
LCD_D4_DIR = 0;
LCD_D5_DIR = 0;
LCD_D6_DIR = 0;
LCD_D7_DIR = 0;
__delay_ms(40);
LCD_Cmd(3);
__delay_ms(5);
LCD_Cmd(3);
__delay_ms(5);
LCD_Cmd(3);
__delay_ms(5);
LCD_Cmd(LCD_RETURN_HOME);
__delay_ms(5);
LCD_Cmd(0x20 | (LCD_TYPE << 2));
__delay_ms(50);
LCD_Cmd(LCD_TURN_ON);
__delay_ms(50);
LCD_Cmd(LCD_CLEAR);
__delay_ms(50);
LCD_Cmd(LCD_ENTRY_MODE_SET | LCD_RETURN_HOME);
__delay_ms(50);
}
UART library for PIC:
void UART_Init(const uint32_t baud_rate)
{
int16_t n = ( _XTAL_FREQ / (16 * baud_rate) ) - 1;
if (n < 0)
n = 0;
if (n > 255) // low speed
{
n = ( _XTAL_FREQ / (64 * baud_rate) ) - 1;
if (n > 255)
n = 255;
SPBRG = n;
TXSTA = 0x20; // transmit enabled, low speed mode
}
else // high speed
{
SPBRG = n;
TXSTA = 0x24; // transmit enabled, high speed mode
}
RCSTA = 0x90; // serial port enabled, continues receive enabled
}
__bit UART_Data_Ready()
{
return RCIF; // return RCIF bit (register PIR1, bit 5)
}
uint8_t UART_GetC()
{
while (RCIF == 0) ; // wait for data receive
if (OERR) // if there is overrun error
{ // clear overrun error bit
CREN = 0;
CREN = 1;
}
return RCREG; // read from EUSART receive data register
}
void UART_PutC(const char data)
{
while (TRMT == 0); // wait for transmit shift register to be empty
TXREG = data; // update EUSART transmit data register
}
void UART_Print(const char *data)
{
uint8_t i = 0;
while (data[i] != '\0')
UART_PutC (data[i++]);
}
For the hardware part, I've use a level shifter between the ESP and the PIC. The TX of the ESP is connected to the RX of the PIC and the RX of the ESP is connected to the TX of the PIC.
Thanks for your help.