ST MCU Finder
安装免费手机应用,
寻找理想的ST MCU

[STM32L4] 基于STM32L4+BC28(全网通) NBIOT开发板原理图教程源码等开...

[复制链接]
1238|42
 楼主 | 2020-1-31 18:20 | 显示全部楼层 |阅读模式
基于STM32L4+BC28(全网通) NBIOT开发板原理图教程源码等开源分享
FCORE_BC28L4 NB-iot原理图、教程和源码
资料下载见附件,电脑登入

源码网盘链接:https://pan.baidu.com/s/18gkI9U1sVvauu_VzuUjauA
提取码:6yd2
1.jpg
2.png

FCORE-BC28L4.zip

12.76 MB, 下载次数: 14

FFCORE_BC28L4教程.pdf

3.36 MB, 下载次数: 18

Quectel_BC28_硬件设计手册_V1.1.pdf

765.89 KB, 下载次数: 12

Quectel_BC35-G&BC28_AT_Commands_Manual_V1.2.pdf

1.97 MB, 下载次数: 10

锝臻科技开源产品介绍(2020-1-14).pdf

1.65 MB, 下载次数: 12

使用特权

评论回复
 楼主 | 2020-1-31 18:22 | 显示全部楼层
基于STM32L433CCUx的NB-Iot物联网开发板教程
基于超低功耗STM32L433系列单片机设计的3G物联网板卡FCORE_BC28L4-EVM的习教程,其物联网模块选用了移远的高性能、低功耗的BC28的NB-Iot模块。支持频段为700MHz,并支持IPv4、IPv6、TCP*、MQTT*等多种通信协议,支持点对点短信的收发及文本和PDU模式,可用于阿里云、天翼云等平台开发。
首先,我们先了解其硬件设计,
板卡大小为:84*52mm;
其引出了BC28的主串口和调试串口;
程序的烧录为STM32通用的SWD口(已引出);
电源指示灯和自定义LED指示灯和网络连接指示灯;
NB网络天线接口;
有MCU RESET按键和BC28 RESET按键供客户使用;
供电方式共有两种,分别为电池供电和USB供电;
支持标准SIM卡和芯片卡;
并将其余接口全部引出,用于给大家自行扩展学习。
详情如图1(SIM卡由于在背面就不进行展示了
2.png

使用特权

评论回复
 楼主 | 2020-1-31 18:24 | 显示全部楼层
接下来我们看看软件部分:
       首先是相关环境的搭建:MDK 5的安装和对应MCU的keil固件包的安装,MDK 5网上很多,安装教程一大堆就不做复述;之后便是CubeMX的安装和对应MCU库包的安装;如果不添加对应AliOS或LiteOS系统的话,现在我们就可以对进物联网这个大板块进发了,这次教程暂时也是没有系统的;所以我们开始物联网之旅吧!
    首先,设计基本的程序,无论是自己移植MDK工程文件还是从CubeMX导出,我们只需要按照原理图将对应的串口配置好就可以了,如图2、图3;


1.png
2.png

使用特权

评论回复
 楼主 | 2020-1-31 18:26 | 显示全部楼层
看了对应原理图,现在我们开始配置CubeMX(我这里用的是5.4版本):
1、开CubeMX,选择File,选择New Project如图4;
1.png
2、选择对应MCU(在左上角搜索框输入对应MCU型号即可),如图5;
2.png
图5

使用特权

评论回复
 楼主 | 2020-1-31 18:27 | 显示全部楼层
3、MCU选好后双击对应MCU,进入系统配置界面,首先需要配置的是系统的时钟,依据原理图,板卡分别使用了外部8MHz高速时钟和32.768KHz的低速时钟,均为无源晶体;所以我们在System Core分类里面找到RCC,或直接在搜索框搜索RCC进行配置,详细配置如图6(这里不能选择BYPASS CLOCK SOURCE哦因为它是有源晶振的配置);
1.png
图6

使用特权

评论回复
 楼主 | 2020-1-31 18:29 | 显示全部楼层
图6
3、然后在RCC选项下面有个SYS,点击之后,Debug配置选Serial Wire,TimebaseSource配置中选TIM6,这样我们就可以用SWD调试;如图7;
1.png
图7

使用特权

评论回复
 楼主 | 2020-1-31 18:30 | 显示全部楼层
3、接下来配置LPUART1,在Connectivity分类中选择LPUART1,模式选择Asynchronous即异步模式,Baud Rate按BC28支持的波特率填写,我们按其默认波特率9600填写,字节长度为设为8,DataDirection选择Receive and Transmit即收发模式,如图8;
1.png
图8

使用特权

评论回复
 楼主 | 2020-1-31 18:31 | 显示全部楼层
3、然后我们在LPUART1 Configuration 中选择DMA Settings,在该选项框中点击Add,将DMA Request栏中选LPUART_RX,其余不用配置,如图9;
1.png
图9

使用特权

评论回复
 楼主 | 2020-1-31 18:33 | 显示全部楼层
3、细心的朋友客能发现CubeMX上面的LPUART1对应的引脚和原理图上面是不一样,这里是PA2和PA3而原理图上面是PB10和PB11,所以这里需要我们手动去复用PB10,PB11,在CubeMX右侧的单片机图片中找到PB10,点击鼠标左键,找到LPUART1_RX选项鼠标左键点击该选项,这样就把LPUART1_RX复用到PB10,PB11重复上面步骤即可,如图10;
1.png
图10

使用特权

评论回复
 楼主 | 2020-1-31 18:34 | 显示全部楼层
3、这里做个简单的测试LED指示,从原理图中找到LED4的引脚为PA4,我们把它配置为推挽输出,输出为LED非工作状态,即LED为熄灭状态,并命名为STATE_LED,如图11;
1.png

使用特权

评论回复
 楼主 | 2020-1-31 18:35 | 显示全部楼层
3、现在到了配置时钟线的时候了,STM32L433最大支持80MHz配置系统时钟80MHz,选择外部时钟源,如图12;
1.png

使用特权

评论回复
 楼主 | 2020-1-31 18:36 | 显示全部楼层
到这里程序的配置就完成了,接下来我们需要设置工程路径和工程名字;值得注意的是工程路径是不能包含中文路径的,点击左侧CodeGennerator在该栏中勾选右侧如下图红色区域:


1.png

使用特权

评论回复
 楼主 | 2020-1-31 18:37 | 显示全部楼层
然后点击左侧Project在Toolchain(IDE)选择MDK-RAM,如图13;
1.png

使用特权

评论回复
 楼主 | 2020-1-31 18:38 | 显示全部楼层
最后点击右上角GENERATE CODE,然后回弹出是否打开工程或打开对应文件夹,选择Open Project,这样我们就完成了基本配置代码的生成了,并且在keil5中打开了。
    用Keil打开代码工程后,首先进行编译,编译后发现是0 error、0 warning的话,说明你的代码已经好了,如果你选择的路径有中文字符,则工程就会出现很多错误,如图14。
1.png

使用特权

评论回复
 楼主 | 2020-1-31 18:39 | 显示全部楼层
现在进行添加自己的代码,主要为板卡自动驻网等的检查函数;使用_BC28_CMD_()函数进行对BC28模块命令的发送,使用之前配置的LPUART1串口,驻网成功和数据的发送;在使用程序测试的时候建议发送ATE命令开启命令会回音模式,这样在测试过程中就能知道测试到那一步出问题了。首先在自己添加的xxx.h文件添加命令宏定义,如下:
******************************命令宏定义*****************************
#define CMD_AT_RESET                                                 "AT+NRB\r\n"
#define CMD_AT                                                                         "AT\r\n"
#define CMD_ATI                    "ATI\r\n"
#define CMD_CUFN_RESET                                 "AT+CFUN=0\r\n"
#define CMD_CUFN_ASK                                 "AT+CFUN?\r\n"
#define CMD_CUFN_SET                                 "AT+CFUN=1\r\n"
#define CMD_NTSETID                                         "AT+NTSETID=1,863703030570134\r\n"
#define CMD_NCDP                                                                "AT+NCDP=49.4.85.232,5683\r\n"//"AT+NCDP=117.60.157.137,5683\r\n"
#define CMD_NCDP_ASK                                                "AT+NCDP?\r\n"
#define CMD_CGPADDR                                                 "AT+CGPADDR\r\n"
#define CMD_SINGNALASK                                         "AT+NUESTATS\r\n"
#define CMD_ICID                                                                "AT+CIMI\r\n"
#define CMD_ECHO                "ATE\r\n"

#define CMD_DUTONET                                         "AT+NCONFIG=AUTOCONNECT,TRUE\r\n"
#define CMD_CGDCONT           "AT+CGDCONT=1,\"IP\",\"psm0.edrx0.ctnb\"\r\n"
#define CMD_CGDCONT_ASK                                 "AT+CGDCONT?\r\n"
#define CMD_NNMI_SET                                                "AT+NNMI=1\r\n"
#define CMD_NSMI_SET                                                 "AT+NSMI=1\r\n"
#define CMD_NNMI_ASK                                                 "AT+NNMI?\r\n"
#define CMD_NSMI_ASK                                                 "AT+NSMI?\r\n"

#define CMD_SEND_DAT                                                 "AT+NMGS=18,980012010001123456785A2608CE00A3E1FF\r\n"
#define CMD_NBAND_ASK                                         "AT+NBAND?\r\n"
#define CMD_NBAND_SET                                         "AT+NBAND=5\r\n"
#define CMD_CIMI                                                                 "AT+CIMI\r\n"
#define CMD_CGATT_SET                                         "AT+CGATT=1\r\n"
#define CMD_CGATT_RESET                                 "AT+CGATT=0\r\n"
#define CMD_CGATT_ASK                                         "AT+CGATT?\r\n"
#define CMD_CSQ                                                                 "AT+CSQ\r\n"
#define CMD_CEREG_ASK                                         "AT+CEREG?\r\n"
#define CMD_CEREG_SET                                         "AT+CEREG=1\r\n"
#define CMD_CSCON_ASK                                         "AT+CSCON?\r\n"
#define CMD_CSCON_SET                                         "AT+CSCON=1\r\n"
#define CMD_PSM_SET                                                 "AT+CPSMS=2\r\n"
#define CMD_EDRX_SET                                                 "AT+CEDRXS=3\r\n"
#define CMD_send_TexT                                         "AT+NMGS=21,9800170100010000000100000001FFFF000100FF47\r\n"

#define DCT_SIGNALASK                 "Signal power"
#define DCT_RCVE                                   "+NNMI:18,"
#define DCT_RST                                                                 "Neul"
#define DCT_OK                                                                         "OK"
#define DCT_MNMI_1                                                  "+NNMI:1"
#define DCT_NSMI_1                                             "+NSMI:1"
#define DCT_CUFN_ASK_1                                         "+CFUN:1"
#define DCT_CUFN_ASK_0                                         "+CFUN:0"
#define DCT_CGDCONT                                                 "+CONT:1"
#define DCT_BAND5                                                         "+NBAND:5"
#define DCT_ADCGATT1                                                 "+CGATT:1"
#define DCT_ADCGATT0                                                 "+CGATT:0"
#define DCT_ADCSQ                                                         "+CSQ"
#define DCT_CSCON1                                                         "+CSCON:0,1"
#define DCT_CSCON0                                                         "+CSCON:0,0"
#define DCT_NSONMI                                                         "+NSONMI:"
#define DCT_CEREG1                                                         "+CEREG:0,1"
#define DCT_CEREG0                                                         "+CEREG:0,1"
#define DCT_SOCKET_OFF                                        "AT+NSOCL=0\r\n"
#define DATA_IP                                                                 "AT+NSOST=0,120.24.184.124,8010,%c,%s\r\n",'8',"727394ACB8221234"
#define DATA_SOCKET                                                 "AT+NSOCR=DGRAM,17,3568,1\r\n"
#define DATA_IP                                                                 "AT+NSOST=0,120.24.184.124,8010,%c,%s\r\n",'8',"727394ACB8221234"
#define DATA_SD_IP                                                        "AT+NSOST=0,120.24.184.124,8010"
#define DATA_SD_APN                                                 "AT+CGDCONT=1,\042IP\042,\042HUAWEI.COM\042\r\n"

使用特权

评论回复
 楼主 | 2020-1-31 18:39 | 显示全部楼层
void _BC28_SET_(void);

添加完宏定义后再给自己添加的xxx.c文件添加对应函数如下:
******************************驻网测试函数***************************
void _BC28_SET_(void)
{
        _DEBUGE_FLEG=0;

        //关闭操作标志位;
//                _BC28_RESET_();

        printf("AT+NRB\r\n ");
        HAL_Delay(2000);
        _BC28_CMD_(CMD_ECHO,                             DCT_OK,300,4);
        _BC28_CMD_(CMD_CUFN_ASK,                                                DCT_CUFN_ASK_1,300,4);
        _BC28_CMD_(CMD_CUFN_SET,                                                        DCT_OK,300,4);
        _BC28_CMD_(CMD_EDRX_SET,                                                        DCT_OK,300,4);
        _BC28_CMD_(CMD_NCDP,                                                                        DCT_OK,1000,4);
        _BC28_CMD_(CMD_NCDP_ASK,                                                        DCT_OK,300,4);
        _BC28_CMD_(CMD_CGATT_SET,                                DCT_OK,300,2);
        _BC28_SIGNALASK_();
        if(_BC28_CMD_(CMD_CGATT_ASK,                                DCT_ADCGATT1,2000,4))
        {
                        HAL_GPIO_WritePin(STATE_LED_GPIO_Port, STATE_LED_Pin, GPIO_PIN_SET);
        }
        _BC28_CMD_(CMD_CGPADDR,                                                                DCT_OK,300,4);
        _BC28_CMD_(CMD_NNMI_SET,                                                        DCT_OK,300,4);
        _BC28_CMD_(CMD_NSMI_SET,                                                        DCT_OK,300,4);
        _BC28_CMD_(CMD_NNMI_ASK,                                                        DCT_MNMI_1,300,4);
        _BC28_CMD_(CMD_NSMI_ASK,                                                        DCT_NSMI_1,300,4);
        HAL_Delay(200);
        if(_BC28_CMD_1(CMD_send_TexT,                                        DCT_RCVE,600,3,4))
        {
                _BC28_SET_();
        }
        _BC28_CMD_(CMD_AT,                                                                                DCT_OK,300,20);
HAL_GPIO_WritePin(STATE_LED_GPIO_Port,STATE_LED_Pin,GPIO_PIN_RESET);       
_DEBUGE_FLEG=1;
}
        这个测试函数的基本操作首先使用发送AT+NRB对模块进行重启,重启的过程大概需要2s左右,所以这里需要做相应的延时,防止后面命令发出去后被忽略,重启后使用char _BC28_CMD_(char* pstr_CMD,char* pstr_DCT,int delay_us,int MAXTRY)发送对应命令进行设置,从上图中可以看到基本都是最这个函数的调用,而这个函数实际是将串口的发送函数进行封装了,里面添加了延时,发送次数等参数的设置,熟悉C编程的朋友看到这里也就明白了,我们                    实际也是使用printf函数进行命令的发送,这里涉及到对串口发送函数的重定向。发送函数的重定向可以使用直接用寄存器进行,memset()和strstr()函数需要包含string.h头文件,由于用到printf函数所以还需要xxx.h文件开头添加如下是代码:
xxx.c文件中添加如下代码
***************************xxx.c中命令发送函数**********************
char _BC28_CMD_1(char* pstr_CMD,char* pstr_DCT,int delay_us,int MAXTRY,int MAXWAT)
{
        char *strx;
        int i=0,j=0;
        memset(RX_BUFFER_lp, NULL, 200);
        strx=NULL;
        while(strx==NULL && j < MAXTRY)
        {
                memset(RX_BUFFER_lp, NULL, 50);
                HAL_Delay(50);
                printf("%s",pstr_CMD);
                j++;
                i=0;
                while(strx==NULL && i < MAXWAT)
                {
                        strx=strstr((const char*)RX_BUFFER_lp,(const char*)pstr_DCT);
                        HAL_Delay(delay_us);
                        i++;
                }
        }
        if(strx==NULL )
        {
                return 0;
        }
        else
        {
                return 1;
        }
}

char _BC28_CMD_(char* pstr_CMD,char* pstr_DCT,int delay_us,int MAXTRY)
{
        char *strx;
        int i=0;
        memset(RX_BUFFER_lp, NULL, 200);
        strx=NULL;
        HAL_Delay(50);
        while(strx==NULL && i < MAXTRY)
        {
                memset(RX_BUFFER_lp, NULL, 200);
                printf("%s",pstr_CMD);    //???lpuart????????
                HAL_Delay(delay_us);
                strx=strstr((const char*)RX_BUFFER_lp,(const char*)pstr_DCT);
                i++;
        }
        if(strx==NULL )
                {
                        return 0;
                }
                else
                        {
                                return 1;
                        }
}
char _BC28_SIGNALASK_(void)
{
        memset(RX_BUFFER_lp, NULL, 200);
        char CSQ=99;
        char *strx;
        int i=0,j=0;
        strx=NULL;
        HAL_Delay(50);
        while(strx==NULL && i < 30 )
        {
                printf("%s",CMD_CSQ);                                                                               
                HAL_Delay(200);
                strx=strstr((const char*)RX_BUFFER_lp,(const char*)DCT_ADCSQ);
                i++;
                if(strx)
                        {
                                CSQ=(strx[5]-0x30)*10+(strx[6]-0x30);
                                if(CSQ==99)
                                        {
                                                memset(RX_BUFFER_lp, NULL, 50);
                                                while(CSQ==99 && j < 300)
                                                {
                                                        printf("%s",CMD_CSQ);                                                                                ֵ
                                                        HAL_Delay(400);
                                                        strx=strstr((const char*)RX_BUFFER_lp,(const char*)DCT_ADCSQ);
                                                        CSQ=(strx[5]-0x30)*10+(strx[6]-0x30);
                                                        j++;
                                                }
                                        }
                                }
                        }
        if(CSQ==99)
        {
                return 0;
        }
        else
                {
                        return CSQ;
                }
        }
char _BC28_SIGNALASK_(void)
{
        memset(RX_BUFFER_lp, NULL, 200);
        char CSQ=99;
        char *strx;
        int i=0,j=0;
        strx=NULL;
        HAL_Delay(50);
        while(strx==NULL && i < 30 )
        {
                printf("%s",CMD_CSQ);                                                                                //查看获取CSQ值
                HAL_Delay(200);
                strx=strstr((const char*)RX_BUFFER_lp,(const char*)DCT_ADCSQ);
                i++;
                if(strx)
                        {
                                CSQ=(strx[5]-0x30)*10+(strx[6]-0x30);//信号转码
                                if(CSQ==99)
                                        {
                                                memset(RX_BUFFER_lp, NULL, 50);
                                                while(CSQ==99 && j < 300)
                                                {
                                                        printf("%s",CMD_CSQ);                                                                                //查看获取CSQ值
                                                        HAL_Delay(400);
                                                        strx=strstr((const char*)RX_BUFFER_lp,(const char*)DCT_ADCSQ);
                                                        CSQ=(strx[5]-0x30)*10+(strx[6]-0x30);//信号转码
                                                        j++;
                                                }
                                        }
                                }
                        }
        if(CSQ==99)
        {
                return 0;
        }
        else
                {
                        return CSQ;
                }
        }

使用特权

评论回复
 楼主 | 2020-1-31 18:40 | 显示全部楼层
***********************xxx.c中需添加的定义************************
extern uint8_t                         RX_BUFFER_lp[200];
extern uint8_t                         RX_Conter_lp;
extern __IO char _DEBUGE_FLEG;

在usart.c中添加如下代码
*****************************串口重定向函数**************************
#include "stdio.h"
int fputc(int ch,FILE *f)
{
        while((LPUART1->ISR&0x40)==0);
        LPUART1->TDR=ch;
        return ch;
}

使用特权

评论回复
 楼主 | 2020-1-31 18:40 | 显示全部楼层
在usart.h中添加如下代码
*****************************宏定义变量******************************
#define Rcive_size_lp 200
#define Rcive_size_1 10

使用特权

评论回复
 楼主 | 2020-1-31 18:41 | 显示全部楼层
xxx.h文件开头添加如下代码
*************************需要包含的头文件代码************************
#include "usart.h"
#include "main.h"
#include "string.h"
这里只是对函数示例,因为这个很常用,基本都清楚,但是考虑到初学者可能忘记这一步所以贴这里。

使用特权

评论回复
 楼主 | 2020-1-31 18:41 | 显示全部楼层
现在测试的程序已经完全OK了,但是还差了很重要的一步,就是我们串口通信的服务函数还没有写,在stm32lxx_it.c文件的最后面添加两个串口的中断服务函数,添加完下面函数后,单片机就能及时收到对应信息并作相应处理了。
stm32lxx_it.c文件中添加如下是代码
*************************外部宏定义重申明***************************
extern UART_HandleTypeDef hlpuart1;
extern uint8_t                         RX_Conter_1;

extern uint8_t                         RX_BUFFER_LPTMP[200];
extern uint8_t                         RX_BUFFER_lp[200];
extern uint8_t                         RX_Conter_lp;

extern uint8_t                         RX_BUFFER_1TMP[10];
extern uint8_t                         RX_BUFFER_1[10];
extern uint8_t                         RX_Conter_1;
***********************LPUSAR中断服务函数***************************
void LPUART1_IRQHandler(void)
{
  /* USER CODE BEGIN LPUART1_IRQn 0 */
        char *xstrx=NULL;
  uint32_t tmp_flag = 0;
  uint32_t temp;
  /* USER CODE END LPUART1_IRQn 0 */
  HAL_UART_IRQHandler(&hlpuart1);
  /* USER CODE BEGIN LPUART1_IRQn 1 */
  tmp_flag = __HAL_UART_GET_FLAG(&hlpuart1,UART_FLAG_IDLE);
    if((tmp_flag != RESET))
     {   
      __HAL_UART_CLEAR_IDLEFLAG(&hlpuart1);
      HAL_UART_DMAStop(&hlpuart1);
      temp  = hdma_lpuart_rx.Instance->CNDTR;
      RX_Conter_lp =200- temp;
      }
  HAL_UART_Receive_DMA(&hlpuart1, RX_BUFFER_lp,200);
  }

使用特权

评论回复
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

我要发帖 投诉建议 创建版块 申请版主

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式

论坛热帖

在线客服 快速回复 返回顶部 返回列表