手上这块 DA16200 是 PMOD 封装的,插上去模组挂在 uart0,console 单独走 uart9,两路分开,RESET 接 P608、低有效。

第一次跑的代码很简单:拉低 RESET 复位一下,等 500ms,发 AT\r\n,然后死循环把收到的字节打出来。烧进去,串口一片安静,等了六秒一个字节都没有。
先怀疑波特率。翻串口寄存器看了眼状态位:
SSR = 0xF2 (RDRF / ORER / FER 全是 1)
有数据进来,但帧错误——看着就像波特率对不上。于是写了段扫描代码,用 uart_configure() 挨个试 115200、230400、921600。结果一调 uart_configure(),程序直接不动了,串口停在 --- 115200 baud --- 后面再没下文。挂调试器上去看,核在跑没崩,PC 卡在 _isr_wrapper 里,中断风暴。查 NVIC:
ICSR VECTACTIVE = 19 (IRQ 3 = SCI0 的 ERI 错误中断)
帧错误置了位,驱动没注册回调压根不去清标志,ISR 无限重入,主循环再也回不来。把 CONFIG_UART_INTERRUPT_DRIVEN=n 关掉,ERI 进不了 NVIC,风暴没了。顺手在轮询里自己清 SSR 的错误位——RA 的接收器 ORER 一置位就停止收数据,不清会直接聋掉。
绕这么一大圈,回头看方向从一开始就错了。波特率根本没问题,真正的原因是 DA16200 开机比 MCU 慢得多,500ms 就把 AT 甩过去它还没醒,之前那些 FER 是它上电过程电平乱跳造成的。改成先被动听:复位放开后一直收,等它自己吐东西,收到 +INIT:DONE 再说话。
+INIT:DONE ,0
,0 是正常上电启动的意思。这条一出来后面就顺了:
>>> AT OK
哦耶。
接着摸底,查版本:
>>> AT+VER +VER:RTOS-GEN01-01-11904-000000,SLIB-GEN01-01-11406-000000 OK
想查 MAC,AT+WFMAC=? 给了个 ERROR:-3,后缀写错了,懒得纠结,直接 AT+WFSTAT 里就有:
>>> AT+WFSTAT +WFSTAT:sta0 mac_address=d4:3d:39:37:15:60 wpa_state=SCANNING
D4:3D:39 是 Dialog 的 OUI,对得上。wpa_state=SCANNING 说明射频在干活。扫一下周围:
>>> AT+WFSCAN +WFSCAN:48:7d:2e:08:bd:ec 2437 -59 [WPA-PSK-CCMP+TKIP][WPA2-PSK-CCMP+TKIP][ESS] zhongxinhetai 44:f7:70:14:90:5a 2412 -84 [WPA2-PSK-CCMP][WPS][ESS] Astral-Invasion 46:f7:70:24:90:5a 2412 -84 [ESS] OK
能扫到东西,射频没问题。拿手机开了个热点,SSID 就叫 l,连它:
>>> AT+WFJAPA=l,<密码> OK +WFJAP:1,'l',192.168.49.11
连上直接把 IP 一起返回来了。查详细状态,四次握手走完、AES-CCMP:
key_mgmt=WPA2-PSK pairwise_cipher=CCMP group_cipher=CCMP channel=11 wpa_state=COMPLETED handshake_state=3
DHCP 也拿到了:
>>> AT+NWIP=? +NWIP:0,192.168.49.11,255.255.255.0,192.168.49.1 OK
ping 网关试试。+NWPING 返回的五个数是发送、接收、平均、最小、最大:
>>> AT+NWPING=0,192.168.49.1,4 +NWPING:4,4,5,0,20
发 4 收 4 零丢包。再 ping 个公网的,也通,平均 17ms,走手机热点出去这个延迟正常:
>>> AT+NWPING=0,223.5.5.5,4 +NWPING:4,4,17,10,30
中间有一次 ping 公网返回 +NWPING:4,0,0,0,0 全丢,重跑一遍又好了,应该是热点那头外网抖了一下,不是模组的问题。
基础的通了,开始搞 TCP。电脑上用 python 起个监听在 5000 端口,板子这边发起连接:
>>> AT+TRTC=192.168.49.4,5000,10000 OK
电脑那边立刻打出来,源端口 10000 正是我指定的:
*** CONNECTION ACCEPTED from 192.168.49.11:10000 ***
让电脑往回发一句,模组这边收到,14 个字节一个不差,下行通了:
+TRDTC:1,192.168.49.4,5000,14,HELLO-FROM-PC
然后就卡在上行上了,卡了很久。DA16200 发数据不走普通 AT 行,要用 ESC 命令,0x1B 打头。我按印象里的格式写:
<ESC>S0,192.168.49.4,5000,11,HELLO-BOARD ERROR:-4
改 cid 成 S1、去掉 ip 和 port 只留长度,全是 ERROR:-4。开始瞎试,一次性甩六个变体过去,每个带不同 payload,电脑那头收到哪个就知道哪个对:
<ESC>S1,... ERROR:-4 <ESC>S2,... ERROR:-4 <ESC>S0,... ERROR:-4 <ESC>S1,11,... ERROR:-4 <ESC>H1,... ERROR:-1 AT+TRDTC=... ERROR:-1
电脑一个字节没收到,但有个意外收获——-1 和 -4 不一样。<ESC>H 和 AT+TRDTC 给的是 -1,<ESC>S 给的是 -4,说明 <ESC>S 这个命令模组认识,只是参数不满意,前缀对了问题在参数里。那就把参数一个个枚举,cid 从 0 试到 7,再加上补零的长度、省掉长度、省掉地址、空格分隔、两位 cid、结尾加 CRLF,一共 12 个变体一次打过去,全部 ERROR:-4,电脑还是一个字节没收到。只有最后那个带 \r\n 的多吐一个 ERROR:-1,是 CRLF 后面空行被当成新命令了——反过来说明 ESC 命令不需要换行结尾。cid 从 0 到 7 全一个错误码,说明解析在读到 cid 之前就失败了,cid 根本不是变量。猜错三轮。
改成问模组自己支持什么,用 -1 当探针:
AT+HELP ERROR:-1 AT? ERROR:-1 AT+TRTC=? ERROR:-2 AT+TRTS=? ERROR:-4 AT+TRPRT ERROR:-2 AT+TRSAVE OK AT+NWCCRT +NWCCRT:0 OK AT+TRSSL=? ERROR:-1
错误码的意思基本清楚了:-1 没这条命令,-2 参数给少了,-4 参数值不合法。<ESC>S 一直是 -4 从来不是 -2,说明字段个数够,是某个值不对。
不过这轮我干了件蠢事。上面那个 AT+TRSAVE 回了 OK——它把 TR 配置写进 NVRAM 了。下一轮再跑,建连接直接变成:
>>> AT+TRTC=192.168.49.4,5000,10000 ERROR:-4
本地端口 10000 被那个持久化下来的 session 占住了,换成 10007 立刻就好。探测命令的时候不该往里塞 save 类的东西。
到这一步不想再猜了,去找手册。资料包里那三份 PDF——数据手册、EVK 手册、原理图——翻遍了都没有数据发送这一章,AT 命令手册是单独的 UM-WI-003,压根没在包里。那就上网找,Renesas 这份是公开文档,搜到 PDF 下下来,pdftotext 转文本,grep 一下 ESC:
$ grep -n "ESC" at.txt 3473:<ESC>S 3500:<ESC>S010,192.168.0.1,3713,abcde12345 3501:<ESC>S110,0,0,abcde12345 4311:b. <ESC>S18,0,0,12345678 ← Send eight bytes of data "12345678"
看到 S110,0,0,abcde12345 那一刻就明白错哪了。手册第 43 页写得很清楚:
<ESC>S<cid><length>,<remote_ip>,<remote_port>,<data>
cid 和 length 是连在一起的,中间没有逗号。S110 是 cid=1、length=10,不是 S1 加 10。而且 TCP client 的 remote_ip 和 remote_port 要填 0,0,目标本来就是已经连上的那个 server,不用再指定。我一直写成 S1,ip,port,11,data——cid 后面多了个逗号,长度跑到地址后面,地址还填了真值,三处全错。难怪 cid 从 0 枚举到 7 都是同一个报错,解析器读完 S1 看见逗号,把逗号当长度字段,第一步就死。
改过来,发 11 个字节:
>>> <ESC>S111,0,0,UPLINK-AAAA OK
电脑那边:
*** RECEIVED 11 bytes: b'UPLINK-AAAA' ***
成了。再来个 37 字节的:
>>> <ESC>S137,0,0,DA16200-UPLINK-TEST-PACKET-0123456789 OK *** RECEIVED 37 bytes: b'DA16200-UPLINK-TEST-PACKET-0123456789' ***
手册还说 length 填 0 的话就一直读到 \r 或 \n 为止,试了下也能用:
>>> <ESC>S10,0,0,ZERO-LEN-FORM\n *** RECEIVED 13 bytes: b'ZERO-LEN-FORM' ***
三种形式都通,字节数一个不差。
我要赚赏金
