我是靠谱客的博主 年轻云朵,这篇文章主要介绍物联网-移远M26模块OpenCPU开发第1讲,现在分享给大家,希望可以做个参考。

心心恋恋的基于移远M26模块设计的用于开发OpenCPU功能的板子终于完成,废话少说,直接上图:

对于板子外观这里不作讨论,毕竟不是我设计的,期望能用吧。

可能是由于设计者经验不足的原因吧。我刚拿到板子的时候一看,心想坏了。貌似串口没有进行电平匹配,找来原理图纸一看,还真的没有进行电平匹配。呵呵,这个时候我还能说啥,自己搭电平匹配电路吧。我又打开了M26 OpenCPU硬件参考手册,找到串口设计章节,如下图:

手册下载地址参见:M26 OpenCPU硬件设计参考手册  。

找来了需要的元器件,手工焊接,有点丑陋,不喜勿喷哈。成品如下图:

由于使用的是笔记本电脑开发,所以找来一根以前工程使用剩下来的USB转TTL线,与自制电平匹配电路板连接起来,如下图:

接下来我就将M26电路板上的串口引脚引出来连接至自制电平匹配电路板上,效果如下:

好了,到此OpenCPU开发所需的硬件已经准备好了。我们就通电连上电脑试一下效果吧。

呵呵,果然,不可能那么顺利的。

连上后打开串口工具,给其发送AT指令,串口没有返回OK,而是直接返回AT,而且串口还会时不时的返回00。不过至少可以证明M26模块没有问题,我想着可能是供应商知道我们是要使用OpenCPU功能,直接烧录了测试代码吧。毕竟一上电板子上的指示灯不停的闪烁、蜂鸣器不停的响。那行,我就直接下载一次M26内核试一下。

打开QFlash 4.8烧录软件,选择好串口号和烧录文件,如下:

操作方法参见qflash用户指导手册:Quectel_QFlash_OpenCPU_User_Guide_V1.0

工具下载地址:qFlash v4.8

点击Start按钮后,重新给电路板上电,看到下面的进度条在前进,很是激动,心想就要成功了。

呵呵,没错,又出问题了,此时一万只草泥马从心中经过。错误如下图:

通过查看qflash用户指导手册中找到引起这个错误的原因,原来是下载时电压不稳定或者是下载线缆连接不稳定,如下图:

好了,知道问题了就来解决问题吧。下载线缆连接肯定不会出错,毕竟串口调试助手一直收发都没有出问题,那就只能是电路板供电问题了,继续查看原理图。看到供电电路貌似也没有问题,这时我又犯愁了,到底怎么回事呢?这时,一个地方引起了我的注意,那就是电路板上的复位电路,如下图:

使用外部自带看门狗功能的芯片进行复位的,必须给其喂狗,这个芯片才会正常工作,不输出复位信号。说明如下:

数据手册参见:SGM706-SYSB

从上图可知喂狗的引脚连接的是M26的16号引脚,通过引脚图可知是NETLIGHT引脚。如下图:

参见硬件设计手册:M26 OpenCPU硬件设计参考手册 

所以就需要M26的NETLIGHT引脚不停的给复位芯片喂狗才行,即必须在1.6s内有一个电平变化。我想就是这个导致,此时M26模块内应该没有这个信号,通过测量,NETLIGHT引脚的确没有电平变化的信号。这就导致M26一直在复位,无法提供稳定的电源给其下载flash。

问题找到了,我就纳闷了,为啥要这么设计,问一下设计人员,得到的回复竟然是到时候M26芯片会固化程序进去,装上就可以正常使用了。暂时移远提供的芯片没有固化这个功能,我也是无语了,控制程序不是还得我们来设计吗,这样搞的话,测试得多麻烦。

啥也不说了,解决问题吧。既然是复位引起的,那就在下载时跳过它吧。通过分析原理图,发现这个芯片的复位引脚是通过控制一个三极管驱动两路MOS管来断M26模块供电电源来实现复位的,那就直接跳过这个三极管,让MOS管一直导通,也就是让Q3的G极一直为低电平即可。电路如下:

          

我想那就直接焊接一根杜邦线,下载时短接GND应该就可以了吧。焊接好后立马测试一下,果然可以了。就是下载时比较麻烦,而且速度老慢了,下载内核耗时400多秒,不知是不是就是这样,还是电路的问题。

到此,重新下载内核后,就需要下载运行程序(含喂狗功能)进去看一下效果了,原来第一次上电时的指示灯和蜂鸣器工作是M26不停复位导致,我还以为是M26自带的测试代码,大写的尴尬。下载测试代码方法参考如下文档,里面有详细操作步骤:Quectel_QFlash_OpenCPU_User_Guide_V1.0。

至于如何编写程序,以及如何编程环境搭建,参考如下文档:

编程环境安装与配置:Quectel_OpenCPU_GCC_Installation_Guide_V1.1

编写程序快速入门:Quectel_OpenCPU_Quick_Start_Application_Note_V1.1

开发工具包:M26_OpenCPU_GS3_SDK_V2.0

编程参考文档:M26 OpenCPU用户指导手册

测试代码主要实现如下功能:

1.给外部复位芯片喂狗;

2.控制板子上的WORK指示灯闪烁,频率为1S;

3.串口打印相关信息。

下面我们来实现这些功能,需要给外部复位芯片喂狗,就得配置相关引脚为输出功能,初始化代码如下:

由于喂狗是周期性的,所以需要定时器功能,实现500ms定时器中断,方法如下:

实现work指示灯闪烁,图纸如下:

32号引脚是PCM_IN,初始化代码如下:

需要实现闪烁,正好可以再定时器回调函数里实现。如下:

因为板子上只使用了M26的主串口,所以此功能实现如下:

编程详请参考相关手册,完整代码如下:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
/***************************************************************************** * Copyright Statement: * -------------------- * This software is protected by Copyright and the information contained * herein is confidential. The software may not be copied and the information * contained herein may not be used or disclosed except with the written * permission of Quectel Co., Ltd. 2013 * *****************************************************************************/ /***************************************************************************** * * Filename: * --------- * main.c * * Project: * -------- * OpenCPU * * Description: * ------------ * * 测试代码 * * Usage: * ------ * Compile & Run: * * Set "C_PREDEF=-D __CUSTOMER_CODE__" in gcc_makefile file. And compile the * app using "make clean/new". * Download image bin to module to run. * * Author: 顾小豆 * * *============================================================================ * HISTORY *---------------------------------------------------------------------------- * ****************************************************************************/ #ifdef __CUSTOMER_CODE__ #include "ql_trace.h" #include "ql_system.h" #include "ql_gpio.h" #include "ql_stdlib.h" #include "ql_error.h" #include "ql_uart.h" #include "ql_timer.h" #include "ql_type.h" #include "ql_error.h" // 串口輸出配置,串口1 #define DEBUG_ENABLE 1 #if DEBUG_ENABLE > 0 #define DEBUG_PORT UART_PORT1 #define DBG_BUF_LEN 512 static char DBG_BUFFER[DBG_BUF_LEN]; #define APP_DEBUG(FORMAT,...) { Ql_memset(DBG_BUFFER, 0, DBG_BUF_LEN); Ql_sprintf(DBG_BUFFER,FORMAT,##__VA_ARGS__); if (UART_PORT2 == (DEBUG_PORT)) { Ql_Debug_Trace(DBG_BUFFER); } else { Ql_UART_Write((Enum_SerialPort)(DEBUG_PORT), (u8*)(DBG_BUFFER), Ql_strlen((const char *)(DBG_BUFFER))); } } #else #define APP_DEBUG(FORMAT,...) #endif // 定义控制引脚相关变量 static Enum_PinName g_wtd_gpioPin = PINNAME_NETLIGHT; // 外部看门狗控制引脚 static Enum_PinName g_work_gpioPin = PINNAME_PCM_IN; // WORK指示灯控制引脚 // 定义定时器相关变量 static u32 m_myTimerId = 2014; // 定时器ID static u32 m_nInterval = 500; // 500ms中断 static void Callback_OnTimer(u32 timerId, void* param); // 定时器回调函数 // 定义串口使用变量 static u8 m_Read_Buffer[1024]; // 串口接收缓存 // 串口回调函数 static void CallBack_UART_Hdlr(Enum_SerialPort port, Enum_UARTEventType msg, bool level, void* customizedPara); // GPIO引脚初始化函数 static void GPIO_Program(void) { // 初始化NET指示灯引脚,低电平,无上下拉配置 Ql_GPIO_Init(g_net_gpioPin, PINDIRECTION_OUT, PINLEVEL_LOW, PINPULLSEL_DISABLE); Ql_GPIO_SetLevel(g_net_gpioPin, PINLEVEL_LOW); // 设定NET引脚为低电平 // 初始化外部看门狗引脚,低电平,无上下拉配置 Ql_GPIO_Init(g_wtd_gpioPin, PINDIRECTION_OUT, PINLEVEL_LOW, PINPULLSEL_DISABLE); // 初始化外WORK指示灯引脚,低电平,无上下拉配置 Ql_GPIO_Init(g_work_gpioPin, PINDIRECTION_OUT, PINLEVEL_LOW, PINPULLSEL_DISABLE); Ql_GPIO_SetLevel(g_work_gpioPin, PINLEVEL_LOW); // 设定WORK引脚为低电平 // 初始化蜂鸣器引脚,低电平,无上下拉配置 Ql_GPIO_Init(g_beep_gpioPin, PINDIRECTION_OUT, PINLEVEL_LOW, PINPULLSEL_DISABLE); Ql_GPIO_SetLevel(g_beep_gpioPin, PINLEVEL_LOW); // 设定蜂鸣器引脚为低电平 // 初始化输出端口引脚,低电平,无上下拉配置 Ql_GPIO_Init(g_out_gpioPin, PINDIRECTION_OUT, PINLEVEL_LOW, PINPULLSEL_DISABLE); Ql_GPIO_SetLevel(g_out_gpioPin, PINLEVEL_LOW); // 设定输出端口引脚为低电平 // 睡眠 500ms,点亮NET指示灯.通过串口打印相关信息 Ql_Sleep(500); Ql_GPIO_SetLevel(g_net_gpioPin, PINLEVEL_HIGH); APP_DEBUG("<-- 获取NET控制引脚电平: %d -->rn", Ql_GPIO_GetLevel(g_net_gpioPin)); APP_DEBUG("<-- 点亮NET指示灯 -->rn"); } // 定时器配置函数 static void TIMER_Program(void) { // 注册定时器2014及定时器回调函数 Ql_Timer_Register(m_myTimerId, Callback_OnTimer, NULL); // 开始定时器2014 Ql_Timer_Start(m_myTimerId, m_nInterval, TRUE); } // 串口初始化函数 static void UART_Program(void) { s32 ret; // 注册串口1和串口回调函数 ret = Ql_UART_Register(UART_PORT1, CallBack_UART_Hdlr, NULL); // 注册失败打印相关信息 if (ret < QL_RET_OK) { APP_DEBUG("Fail to register serial port[%d], ret=%drn", UART_PORT1, ret); } // 打开串口1 波特率115200 无流控 ret = Ql_UART_Open(UART_PORT1, 115200, FC_NONE); // 打开失败打印相关信息 if (ret < QL_RET_OK) { APP_DEBUG("Fail to open serial port[%d], ret=%drn", UART_PORT1, ret); } } // 喂狗函数 static void feed_wtd(void) { s32 gpioLvl = Ql_GPIO_GetLevel(g_wtd_gpioPin); if (PINLEVEL_LOW == gpioLvl) { // 置位看门狗控制引脚 Ql_GPIO_SetLevel(g_wtd_gpioPin, PINLEVEL_HIGH); APP_DEBUG("<-- 外部看门狗喂狗 -->rn"); } else { // 复位看门狗控制引脚 Ql_GPIO_SetLevel(g_wtd_gpioPin, PINLEVEL_LOW); APP_DEBUG("<-- 外部看门狗喂狗 -->rn"); } } // 蜂鸣器控制函数 static void beep_ctrl(void) { } /************************************************************************/ /* The entrance for this example application */ /************************************************************************/ void proc_main_task(s32 taskId) { ST_MSG msg; float g_f; UART_Program(); // 调用串口初始化函数 GPIO_Program(); // 调用GPIO初始化函数 TIMER_Program(); // 调用定时器配置函数 // Start message loop of this task while (TRUE) { Ql_OS_GetMessage(&msg); switch(msg.message) { case MSG_ID_USER_START: break; default: break; } } } static void Callback_OnTimer(u32 timerId, void* param) { static u16 timerCnt[10] = {0}; feed_wtd(); if(timerCnt[0]++ >= 2) { s32 gpioLvl = Ql_GPIO_GetLevel(g_work_gpioPin); if (PINLEVEL_LOW == gpioLvl) { // 点亮work指示灯 Ql_GPIO_SetLevel(g_work_gpioPin, PINLEVEL_HIGH); APP_DEBUG("<-- 点亮work指示灯 -->rn"); } else { // 熄灭work指示灯 Ql_GPIO_SetLevel(g_work_gpioPin, PINLEVEL_LOW); APP_DEBUG("<-- 关闭work指示灯 -->rn"); } timerCnt[0] = 0; } } #endif //__EXAMPLE_GPIO__

欢迎读者提出疑问,可以加群讨论:838839442   微信公众号:物联网技术交流与学习

最后

以上就是年轻云朵最近收集整理的关于物联网-移远M26模块OpenCPU开发第1讲的全部内容,更多相关物联网-移远M26模块OpenCPU开发第1讲内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(77)

评论列表共有 0 条评论

立即
投稿
返回
顶部