Is there any way to catch the response of SIM800L after sending the at command?
for a polling serial read I use this method :
bool tSim8_sendCommand(uint8_t sim_cmd[])
{
    uint8_t simOK[2] = {0}, i=20;
    tSoftSerial1_write(sim_cmd);
    tSoftSerial1_write(&quot;\r\n&quot;);
    while (i--)
    {
        simOK[0] = simOK[1];
        simOK[1] = tSoftSerial1_readChar();
        if(simOK[0] == 'O' || simOK[1] =='K')
        {
            return true;
        }
    }
    return false;
}

the variable i i the while loop, is used just for retries, so the program doesn't get trapped in an infinite loop. the code is self-explanatory. the incoming characters are &quot;pushed&quot; into an array till the array reads &quot;OK&quot;.
for a non-blocking one, it's a bit complicated as you have to define state-machines and concurret loops. here is a method I use for finding out if the last transmission was OK:
void tsim_phase_ok_routine(uint8_t inChar)
{
    if(tsim_aux_buff[0] == 'O' &amp;&amp; tsim_aux_buff[1] =='K' &amp;&amp; tsim_aux_buff[2] =='\r')    
    {
        tsim_status_flag |= (1&lt;&lt;PHASE_OK);
        tsim_status_flag &amp;=~(1&lt;&lt;PHASE_CON_ERR);
        return;
    }
    else    
    {
        tsim_aux_buff[0] = tsim_aux_buff[1];
        tsim_aux_buff[1] = tsim_aux_buff[2];
        tsim_aux_buff[2] = inChar;
        err_timeout--;
    }
    if(!(tsim_status_flag &amp; (1&lt;&lt;PHASE_OK)) &amp;&amp; !err_timeout)
    {
        tsim_status_flag &amp;=~(1&lt;&lt;PHASE_OK);
        tsim_status_flag |= (1&lt;&lt;PHASE_CON_ERR);
    }
    
}

I define &quot;PHASES&quot; to find out which phase is sim800 in. the whole function would be written in RX interrupt service routine and the input character would be fed to it.