uart - PIC16F877A 与 SIM800L
问题描述
我在使用 PIC16F877A UART 时遇到问题。我正在尝试向 SIM800L 发送 AT 命令,但它返回错误。但是当我用 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;
}
从此链接中获取参考在此处输入链接描述
我将 PIC 直接连接到移除 SIM800L 的 PC 并运行下面的代码。当我使用腻子发送你好时,它正在打印你好。
#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;
}
解决方案
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)
推荐阅读
- android - 如何在 android webview 中绘制一个矩形?
- php - 如何将回调函数作为构造函数参数传递并分配给类属性
- google-app-engine - Google App Engine 上的 NodeJS Forge 查看器错误
- javascript - 图例放置 D3
- database - Laravel:如何在刀片视图中使用循环获取姓名、电话号码和其他详细信息
- ios - 如何在 Swift 中获取 UIBarButtonItem 相对于 UIWindow 的框架?
- hadoop - 无法在 Cygwin(Windows 10)上的 Apache Hive 3.0.0 中初始化 HiveServer2 的架构
- excel - 如何通过多行而不是硬代码单元循环 VBA 函数?
- android - React-native,android模拟器不突出检查元素
- sql - 使用滚动窗口从 Sybase SQL 数据库中提取数据