I have problem to interface SIM800L with STM32F103. I just read SIM800L datasheet that UART logic level is on 2.8 V. But the STM32F103,can be operated in 3.3 V. I connected my TX RX pin directly to my MCU. I send AT command but nothing happen. Am I doing something wrong?
Electrical – How to interface SIM800L to UART on STM32F103
cmicrocontrollerserialstm32uart
Related Solutions
I dont understand your confusion. You want to communicate between the two controllers with UART, then ofcourse both of them need UART capabilities and code for this. Your computer has drivers and software for dealing with this, so your microcontroller also needs a driver for it.
Your ATmega32 need UART TX functionality, while AT90USB1287 need UART RX functionality. Having already written both TX and RX for your ATmega32, writing the UART RX routine for AT90 should be a breese. You could add a bitvalue of some kind, identifying that the UART RX on AT90 is coming from your ATmega32, and directly pass it through to USB.
EDIT: Code from AVRFreaks that is written for at90usb1287
#include <avr/io.h>
#include <util/delay.h>
#define RXC (RXC1)
#define TXC (RXC1)
#define UCSRC (UCSR1C)
#define UCSRB (UCSR1B)
#define UCSRA (UCSR1A)
#define UDR (UDR1)
#define UBRRL (UBRR1L)
#define UBRRH (UBRR1H)
#define UBRR (UBRR1)
#define UDRE (UDRE1)
#define RXCIE (RXCIE1)
#define TXEN (TXEN1)
#define RXEN (RXEN1)
#define UCSZ0 (UCSZ10)
#define UCSZ1 (UCSZ11)
#define UMSEL0 (UMSEL10)
#define UMSEL1 (UMSEL11)
#define FRAMING_ERROR (1<<FE1)
#define PARITY_ERROR (1<<UPE1)
#define DATA_OVERRUN (1<<DOR1)
#define DATA_REGISTER_EMPTY (1<<UDRE1)
#define RX_COMPLETE (1<<RXC1)
#define FOSC 16000000
typedef unsigned char Uchar;
typedef unsigned long int Uint32;
#define Wait_USART_Ready() while (!(UCSR1A & (1<<UDRE1)))
#define lowByte(w) ((uint8_t) ((w) & 0xff))
#define highByte(w) ((uint8_t) ((w) >> 8))
int main(void)
{
/* Disable clock division */
clock_prescale_set(clock_div_1);
UBRRH = (Uchar)((((Uint32)FOSC)/((Uint32)USART_BAUDRATE*16)-1)>>8);
UBRRL = (Uchar)(((Uint32)FOSC)/((Uint32)USART_BAUDRATE*16)-1) & 0x0ff;
UCSRB |= (1 << RXEN) | (1 << TXEN);
UCSRC |= (1 << UCSZ1) | (1 << UCSZ0);
char ReceivedByte;
for (;;) // Loop forever
{
while ((UCSRA & (1 << RXC)) == 0) {}; // Do nothing until data have been received and is ready to be read from UDR
ReceivedByte = UDR; // Fetch the received byte value into the variable "ByteReceived"
while ((UCSRA & (1 << UDRE)) == 0) {}; // Do nothing until UDR is ready for more data to be written to it
UDR = ReceivedByte; // Echo back the received byte back to the computer
}
}
After many tries at last it works , the code for anyone who wants it :
#include <xc.h>
// FBS
#pragma config BWRP = WRPROTECT_OFF // Boot Segment Write Protect (Boot Segment may be written)
#pragma config BSS = NO_FLASH // Boot Segment Program Flash Code Protection (No Boot program Flash segment)
#pragma config RBS = NO_RAM // Boot Segment RAM Protection (No Boot RAM)
// FSS
#pragma config SWRP = WRPROTECT_OFF // Secure Segment Program Write Protect (Secure segment may be written)
#pragma config SSS = NO_FLASH // Secure Segment Program Flash Code Protection (No Secure Segment)
#pragma config RSS = NO_RAM // Secure Segment Data RAM Protection (No Secure RAM)
// FGS
#pragma config GWRP = OFF // General Code Segment Write Protect (User program memory is not write-protected)
#pragma config GSS = OFF // General Segment Code Protection (User program memory is not code-protected)
// FOSCSEL
#pragma config FNOSC = PRI // Oscillator Mode (Primary Oscillator (XT, HS, EC))
#pragma config IESO = ON // Internal External Switch Over Mode (Start-up device with FRC, then automatically switch to user-selected oscillator source when ready)
// FOSC
#pragma config POSCMD = XT // Primary Oscillator Source (XT Oscillator Mode)
#pragma config OSCIOFNC = OFF // OSC2 Pin Function (OSC2 pin has clock out function)
#pragma config IOL1WAY = ON // Peripheral Pin Select Configuration (Allow Only One Re-configuration)
#pragma config FCKSM = CSDCMD // Clock Switching and Monitor (Both Clock Switching and Fail-Safe Clock Monitor are disabled)
// FWDT
#pragma config WDTPOST = PS32768 // Watchdog Timer Postscaler (1:32,768)
#pragma config WDTPRE = PR128 // WDT Prescaler (1:128)
#pragma config WINDIS = OFF // Watchdog Timer Window (Watchdog Timer in Non-Window mode)
#pragma config FWDTEN = ON // Watchdog Timer Enable (Watchdog timer always enabled)
// FPOR
#pragma config FPWRT = PWR128 // POR Timer Value (128ms)
#pragma config ALTI2C = OFF // Alternate I2C pins (I2C mapped to SDA1/SCL1 pins)
#pragma config LPOL = ON // Motor Control PWM Low Side Polarity bit (PWM module low side output pins have active-high output polarity)
#pragma config HPOL = ON // Motor Control PWM High Side Polarity bit (PWM module high side output pins have active-high output polarity)
#pragma config PWMPIN = ON // Motor Control PWM Module Pin Mode bit (PWM module pins controlled by PORT register at device Reset)
// FICD
#pragma config ICS = PGD1 // Comm Channel Select (Communicate on PGC1/EMUC1 and PGD1/EMUD1)
#pragma config JTAGEN = OFF // JTAG Port Enable (JTAG is Disabled)
#define FCY 4000000UL
#include <libpic30.h>
int dummy ; int dummy2 ;
char flag =0;
char LReading , HReading ;
unsigned int ADCreading[1] __attribute__((space (dma))) ;
unsigned char UARTsignal[2] __attribute__((space (dma))) ;
void interruptconf(void)
{
SRbits.IPL=000 ; /* CPU operates at 0 level priority NOTE : Each peripheral
interrupt source can be assigned to one of seven priority levels. to disable all set it 111 */
INTCON1bits.NSTDIS=1 ; // Int nesting is disabled
INTCON2bits.ALTIVT=0; // Use standard (default) vector table
IEC0bits.AD1IE = 0 ; IEC0bits.DMA0IE = 1 ; IEC0bits.DMA1IE = 1 ; IEC0bits.U1TXIE = 0 ;
IFS0bits.AD1IF=0 ; IFS0bits.DMA0IF=0 ; IFS0bits.U1TXIF = 0 ; IFS0bits.DMA1IF=0 ;
}
void ADCconf(void)
{
AD1CON1bits.ADON = 0 ; // ADC disabled
AD1CON1bits.ADDMABM = 1 ; // 1 = DMA buffers are written in the order of conversion. The module provides an address to the DMA channel that is the same as the address used for the non-DMA stand-alone buffer
AD1CON1bits.AD12B = 1 ; // 12bit operation mode 1 channel
AD1CON1bits.FORM= 0b00 ; // right justified unsigned
AD1CON1bits.SSRC = 0b111 ; // Internal counter ends sampling and starts conversion (auto-convert)
AD1CON1bits.ASAM=1 ; // sample automaticaly after last conversion Automatic trigger
AD1CON2bits.VCFG=0b000 ; // reference VDD VSS
AD1CON2bits.CSCNA = 0 ; // do not scan inputs
AD1CON2bits.SMPI=0b0000; // Increments the DMA address after completion of every sample/conversion operation
AD1CON2bits.BUFM=0; //Always starts filling the buffer from the start address
AD1CON2bits.ALTS=0 ;// Always uses channel input selects for Sample A
AD1CON3bits.ADRC = 0 ; // Clock Derived from System Clock
AD1CON3bits.SAMC= 2 ; //
AD1CON3bits.ADCS=0b100 ; // 4TCY = TAD the least Tad = 117.6 nano second ,
AD1CON4bits.DMABL = 000 ; // 001 = Allocates 1 words of buffer to each analog input
AD1PCFGLbits.PCFG5=0; //Analog
AD1PCFGLbits.PCFG6=0 ; //Analog
AD1PCFGLbits.PCFG1=0; //Analog
AD1CHS0bits.CH0SA= 0b00001; //Channel 0 positive input is 5
AD1CHS0bits.CH0NA= 0 ; //Channel 0 negative input is VREFL
}
void UartSend(char a)
{
U1TXREG = a ;
while ( U1STAbits.TRMT!=1) // Transmit Shift Register is Empty bit 1 = empty
{
}
}
void UARTconf(void)
{
U1MODEbits.UARTEN=0; //disable UART
U1MODEbits.BRGH=0 ; // Speed Low
U1BRG = 12 ; // 9600
U1MODEbits.PDSEL=00 ; // 8-bit data , no parity
U1MODEbits.STSEL=0 ; // 1 stop bit
U1STAbits.URXISEL= 0b00 ; // Interrupt flag bit is set when a character is received
U1STAbits.UTXISEL0 = 0 ;
U1STAbits.UTXISEL1 = 0 ; // Interrupt generated when any character is transferred to the Transmit Shift register (which ast one location is empty in the transmit buffer)
U1MODEbits.USIDL=0 ; //continue operation in idle mode
U1MODEbits.IREN=0 ; //IrDA encoder and decoder are disabled , works only at low baud
U1MODEbits.RTSMD= 1 ; // RTS simplex mode , no flow control
U1MODEbits.UEN=00 ; // UxTX and UxRX pins are enabled and used; UxCTS, UxRTS and BCLKx pins are controlled by port latches
U1MODEbits.WAKE= 1 ;// wake-up is enabled
U1MODEbits.LPBACK = 0 ; // loopback mode is disabled
U1MODEbits.ABAUD=0 ; // Baud rate measurement disabled or completed
U1STAbits.UTXINV = 0 ; // ?? UxTx idle state is 0 if IREN = 0 Transmit Polarity Inversion bit
U1STAbits.UTXBRK = 0 ; // 0 = Sync Break transmission is disabled or completed
U1STAbits.ADDEN = 0 ; // Address Detect mode disabled
}
void DMA0conf(void)
{ //for ADC
DMA0CONbits.CHEN=0 ; //channel disabled
DMA0PAD =(volatile unsigned int ) &ADC1BUF0 ;
DMA0CNT=0 ; // only one element ;
DMA0REQbits.IRQSEL=0b0001101 ; //ADC
DMA0STA = __builtin_dmaoffset(ADCreading) ;
IFS0bits.DMA0IF = 0; //clear flag
DMA0CONbits.SIZE = 0 ; // word ;
DMA0CONbits.DIR=0 ; // ADC to ram
DMA0CONbits.HALF = 0 ; // Initiate interrupt when all of the data has been moved
DMA0CONbits.NULLW=0 ; // Normal operation
DMA0CONbits.AMODE = 0b01 ; // Register Indirect without Post-Increment mode
DMA0CONbits.MODE= 00 ; // continuous no ping pong
DMA0REQbits.FORCE=0 ; //Auto
DMA0CONbits.CHEN=1 ; //channel enabled
}
void DMA1conf(void)
{ // for TX
DMA1CONbits.CHEN=0 ; //channel disabled
DMA1REQbits.IRQSEL=0b0001100 ;
DMA1PAD =(volatile unsigned int ) &U1TXREG ;
DMA1CNT=1 ; // only two element ;
DMA1STA = __builtin_dmaoffset(UARTsignal) ;
IFS0bits.DMA1IF = 0; //clear flag
DMA1CONbits.SIZE = 1 ; // byte ;
DMA1CONbits.DIR=1 ; // RAM to TX
DMA1CONbits.HALF = 0 ; // Initiate interrupt when all of the data has been moved
DMA1CONbits.NULLW=0 ; // Normal operation
DMA1CONbits.AMODE = 0b00 ; // Register Indirect with Post-Increment mode
DMA1CONbits.MODE= 00 ; // continuous no ping pong
DMA1REQbits.FORCE=0 ; //Auto
DMA1CONbits.CHEN=1 ; //channel enabled
}
void __attribute__((interrupt(no_auto_psv))) _DMA0Interrupt(void)
{
PORTCbits.RC8 = 1 ; // R ON
if(flag == 1 )
{
dummy =ADCreading[0] ;
dummy2 = (0b0000000011111111 & dummy );
LReading = dummy2 ;
dummy2=0b1111111100000000&dummy ;
dummy2=dummy2>>8 ;
HReading= dummy2 ;
UARTsignal[1]=HReading; UARTsignal[0]=LReading ;
flag=0;
}
IFS0bits.DMA0IF = 0 ;
}
void __attribute__((interrupt(no_auto_psv))) _DMA1Interrupt(void)
{
flag = 1 ;
PORTCbits.RC9 = 1 ;
IFS0bits.DMA1IF = 0 ;
}
void __attribute__((interrupt(no_auto_psv))) _U1TXInterrupt(void)
{
IFS0bits.U1TXIF = 0 ;
}
int main()
{
I2C1CONbits.I2CEN=0;//Disables the I2Cx module. All I2C? pins are controlled by port functions
PMCONbits.PMPEN = 0 ; // PMP is disabled
P2TCONbits.PTEN=0 ; // PWM time base is off
PWM2CON1bits.PEN1H=0; // disable PWM pins
PWM2CON1bits.PEN1L = 0 ; //
OSCCON=0x46 ;
OSCCON = 0x57 ;
OSCCONbits.IOLOCK=0 ; // unlock PPS sequence
RPOR11bits.RP23R=0b00011 ; // PORTC7 as TX
RPINR18bits.U1RXR = 22 ; // c6 as RX
OSCCON=0x46 ;
OSCCON = 0x57 ;
OSCCONbits.IOLOCK=1 ; // lock PPS sequence */
TRISCbits.TRISC8=0 ; // Red led output
TRISCbits.TRISC9=0 ; // Green led output
PORTCbits.RC8 = 0 ; // R OFF
PORTCbits.RC9 = 0 ;
interruptconf() ;
DMA0conf() ;
DMA1conf() ;
ADCconf() ;
UARTconf() ;
AD1CON1bits.ADON = 1 ; // ADC enabled
__delay_ms(100) ;
U1MODEbits.UARTEN=1; //enable UART
U1STAbits.UTXEN =1 ; // UARTx transmitt is enabled
DMA1REQbits.FORCE=1 ; //Auto
while(1)
{
}
return 0 ;
}
Best Answer
You have to check the I/O and serial port characteristics in the datasheet of the devices to be sure that logic levels are matched. You need the VIL, VIH, VOL, VOH respectively for the SIM800L and the STM32F103. For the SIM800:
For the STM32F103 the input values that are tested in production:
Theoretically VIL a bit higher and VIH a bit lower.
As you can see there is no problem here as the SIM800's VOLmax (0.1 V) is below the STM32's VILmax (1.155 V). And the SIM800's VOHmin (2.7 V) is above the STM32's VIHmin (2.145 V).
The other direction, STM32F103 output values:
There are several cases, you should calculate with the worst case values, so when the IO current is +20 mA. VOLmax = 1.3 V and VOHmin = 3.3 V - 1.3 V = 2 V.
Now, here come the problems as the SIM800's VILmax is 0.3 V but the STM32's VOLmax is at least 0.4 V. There is a 0.1 V gap in which the input to the SIM800 is undefined.
Also the STM32's VOHmin can be 2 V, 2.4 V or 2.9 V. The 2 V is far below the SIM800's VIHmin 2.5 V. The 2.9 V would probably be fine.
All in all logic level conversion is suggested, it is mentioned in the SIM800's datasheet as well along with a reference circuit.
If your problem persist after doing the level shifting, here are a couple of items that you should check:
\r\n
sequence.