我对PIC16F877A uart有问题。我正在尝试将AT命令发送到SIM800L,但它返回错误。但是,当我尝试使用CP2102模块时,它可以正常工作。有人可以告诉我我的代码是否有问题吗?
具有类似逻辑的此代码在LPC2148上运行,但在PIC16F877A上有问题。
// CONFIG
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = ON // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = ON // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3/PGM pin has PGM function; low-voltage programming enabled)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#include <xc.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define _XTAL_FREQ 20000000
char buff[50], a = 0;
char b, *p;
int conn=0;
int i;
#define RS RD0
#define RW RD1
#define EN RD2
void lcd_cmd(unsigned char cmd)
{
PORTD = (0xF0 & cmd);
RS = 0;
RW = 0;
EN = 1;
__delay_ms(5);
EN = 0;
PORTD = (cmd<<4);
RS = 0;
RW = 0;
EN = 1;
__delay_ms(5);
EN = 0;
}
void lcd_data(unsigned char data)
{
PORTD = (0xF0 & data);
RS = 1;
RW = 0;
EN = 1;
__delay_ms(5);
EN = 0;
PORTD = (data<<4);
RS = 1;
RW = 0;
EN = 1;
__delay_ms(5);
EN = 0;
}
void lcd_string(char *str)
{
while(*str != '\0')
{
lcd_data(*str++);
}
}
void lcd_init()
{
lcd_cmd(0x02);//return to home
lcd_cmd(0x28);///4bitmode
lcd_cmd(0x0C);///cursor off
lcd_cmd(0x06);///increment cursor
lcd_cmd(0x01);///display clear
}
void uart_init()
{
TXSTAbits.TXEN = 1; ////enable transmission
TXSTAbits.BRGH = 1; ////high speed selection bit
RCSTAbits.CREN = 1; ////continuous receive enable
SPBRG = 129; ////baud rate generation 9600 at 20MHz crystal
TRISCbits.TRISC7 = 1; ////enable receive(input) on RC7
TRISCbits.TRISC6 = 0; ////enable transmit(output) on RC6
RCSTAbits.SPEN = 1; ////enable UART
GIE = 1; ///enable UART related interrupts
PEIE = 1;
RCIE = 1;
}
void gsm_send_char(unsigned char data)
{
TXREG = data;
while(PIR1bits.TXIF ==0);
}
char gsm_receive_char()
{
while(PIR1bits.RCIF == 0);
return (RCREG);
}
void gsm_send_string(char *data)
{
while(*data != '\0')
{
gsm_send_char(*data++);
}
}
__interrupt() void uart(void)
{
if(RCIF == 1)
{
b = RCREG;
buff[a] = b;
a++;
//buff[a]='\0';
GIE = 1;
RCIE = 1;
PEIE = 1;
RCIF = 0;
}
}
void gsm_init()
{
if(conn == 0)
{
a=0;
gsm_send_string("AT\r");
__delay_ms(500);
if(strstr(buff, "OK"))
{
lcd_cmd(0x80);
lcd_string(buff);
//a=0;
memset(buff, 0, sizeof(buff));
}
else
{
lcd_cmd(0x80);
lcd_string("AT ERROR");
}
}
}
void main(void)
{
TRISD = 0x00;
lcd_init();
uart_init();
lcd_cmd(0x80);
lcd_string("GSM");
while(1)
{
gsm_init();
__delay_ms(2000);
}
return;
}
我尝试了一点点更改代码并检查了所有错误,并尝试在标志条件下执行命令,现在它在缓冲区中什么也没有接收到,因为它不打印任何内容。有人可以告诉我为什么吗?
// CONFIG
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = ON // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = ON // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3/PGM pin has PGM function; low-voltage programming enabled)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#include <xc.h>
#include <pic16f877a.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#define _XTAL_FREQ 20000000
#define RS RD0
#define RW RD1
#define EN RD2
//#define AT "AT\"
char buff[80], a;
int flag, b, i = 0;
void lcd_cmd(unsigned char cmd)
{
PORTD = (0xF0 & cmd);
RS = 0;
RW = 0;
EN = 1;
__delay_ms(5);
EN = 0;
PORTD = (cmd<<4 & 0xf0);
RS = 0;
RW = 0;
EN = 1;
__delay_ms(5);
EN = 0;
}
void lcd_data(unsigned char data)
{
PORTD = (0xF0 & data);
RS = 1;
RW = 0;
EN = 1;
__delay_ms(5);
EN = 0;
PORTD = (data<<4 & 0xf0);
RS = 1;
RW = 0;
EN = 1;
__delay_ms(5);
EN = 0;
}
void lcd_string(char *str)
{
while(*str != '\0')
{
lcd_data(*str++);
}
}
void lcd_init()
{
lcd_cmd(0x02);//return to home
lcd_cmd(0x28);///4bitmode
lcd_cmd(0x0C);///cursor off
lcd_cmd(0x01);///display clear
lcd_cmd(0x06);///increment cursor
}
void uart_init()
{
SPBRG = 129;
BRGH = 1;
SYNC = 0;
SPEN = 1;
TXEN = 1;
CREN = 1;
GIE = 1;
PEIE = 1;
RCIE = 1;
RCIF = 0;
//TXIE = 1;
TRISC7 = 1;
TRISC6 = 0;
}
void gsm_send_char(unsigned char data)
{
//////////PORTB = 0xff;
TXREG = data;
while(PIR1bits.TXIF == 0);
}
char gsm_receive_char()
{
while(PIR1bits.RCIF == 0);
return RCREG;
}
void gsm_send_string(char *p)
{
while(*p != '\0')
{
gsm_send_char(*p++);
}
}
__interrupt() void isr(void)
{
if(RCIF == 1)
{
a = RCREG;
buff[i] = a;
i++;
if(a == '\r')
{
flag = 1;
}
if(OERR)
{
CREN = 0;
CREN = 1;
}
if(FERR)
{
SPEN = 0;
SPEN = 1;
}
RCIF = 0;
///////PORTB = 0xff;
}
}
void main(void)
{
TRISD = 0x00;
//TRISB = 0x00;
lcd_init();
uart_init();
lcd_cmd(0x80);
lcd_string("GSM TESTING");
while(1)
{
if(flag == 1)
{
i = 0;
gsm_send_string("AT\r\n");
__delay_ms(400);
if(strstr(buff, "OK"))
{
lcd_cmd(0xC0);
lcd_string(buff);
//memset(buff, 0, sizeof(buff));
}
else if(strstr(buff, "ERROR"))
{
lcd_cmd(0xC0);
lcd_string(buff);
// memset(buff, 0, sizeof(buff));
}
flag = 0;
}
}
return;
}
从此链接enter link description here中获取参考
我将PIC直接连接到PC并卸下了SIM800L,然后运行以下代码。当我使用腻子发送问候时,它正在打印问候。
#include <xc.h>
#include <pic16f877a.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#define _XTAL_FREQ 20000000
#define RS RD0
#define RW RD1
#define EN RD2
char buff[80], a;
int flag, b, i = 0;
void lcd_cmd(unsigned char cmd)
{
PORTD = (0xF0 & cmd);
RS = 0;
RW = 0;
EN = 1;
__delay_ms(5);
EN = 0;
PORTD = (cmd<<4 & 0xf0);
RS = 0;
RW = 0;
EN = 1;
__delay_ms(5);
EN = 0;
}
void lcd_data(unsigned char data)
{
PORTD = (0xF0 & data);
RS = 1;
RW = 0;
EN = 1;
__delay_ms(5);
EN = 0;
PORTD = (data<<4 & 0xf0);
RS = 1;
RW = 0;
EN = 1;
__delay_ms(5);
EN = 0;
}
void lcd_string(char *str)
{
while(*str != '\0')
{
lcd_data(*str++);
}
}
void lcd_init()
{
lcd_cmd(0x02);//return to home
lcd_cmd(0x28);///4bitmode
lcd_cmd(0x0C);///cursor off
lcd_cmd(0x01);///display clear
lcd_cmd(0x06);///increment cursor
}
void uart_init()
{
SPBRG = 129;
BRGH = 1;
SYNC = 0;
SPEN = 1;
TXEN = 1;
CREN = 1;
GIE = 1;
PEIE = 1;
RCIE = 1;
RCIF = 0;
//TXIE = 1;
TRISC7 = 1;
TRISC6 = 0;
}
void gsm_send_char(char data)
{
TXREG = data;
while(TXIF == 0);
}
char gsm_receive_char()
{
while(PIR1bits.RCIF == 0);
return RCREG;
}
void gsm_send_string(char *p)
{
while(*p != '\0')
{
gsm_send_char(*p++);
}
}
__interrupt() void isr(void)
{
if(RCIF == 1)
{
a = RCREG;
buff[i] = a;
i++;
RCIF = 0;
}
}
void main(void)
{
TRISD = 0x00;
lcd_init();
uart_init();
lcd_cmd(0x80);
lcd_string("GSM TESTING");
while(1)
{
gsm_send_string("AT");
__delay_ms(400);
//i = 0;
if(strstr(buff, "hello"))
{
lcd_cmd(0xC0);
lcd_string(buff);
}
}
return;
}
答案 0 :(得分:0)
在使用strstr()
函数之前,需要在从UART接收的字符串中添加终止字符。
类似的事情应该起作用:
a=0;
gsm_send_string("AT\r");
__delay_ms(500);
buff[sizeof(buff)-1] = '\0'; // Terminate UART buffer with NULL char
if(strstr(buff, "OK"))
{
lcd_cmd(0x80);
lcd_string(buff);
//a=0;
memset(buff, 0, sizeof(buff));
}
else
{
lcd_cmd(0x80);
lcd_string("AT ERROR");
}
根据您使用的编译器,您可能还需要更改检查字符串中模式的方式。我认为最好这样做:
if(strstr(buff,"OK") != NULL)