假设我正在为Arduino(或任何其他微控制器)开发故障安全机制.换句话说,当主控制器发生故障时,辅助微控制器或单独的电路板应该负责.
两种可能的机制如下.
方法1 - 客户端服务器机制
方法2 - 心跳机制
你们有没有更好的机制来实现这个?
我一直在研究一种使用GSM调制解调器的应用程序,用于以下两种方式之一; 通过向服务器发送GET请求或将数据发送到服务器(使用UDP),使用内置HTTP堆栈检查其状态.我已经尝试了几种不同的方法来保持尽可能可靠,我终于准备寻求帮助了.
我的应用程序是为SIMCOM908模块和PIC18平台编写的(我使用PIC18 Explorer进行开发).
所以问题是有时候调制解调器忙于做某事,而错过命令.作为一个人,我会看到并只是重新发送命令.为我的MCU添加设施以进行超时和重新发送不是问题.
问题是调制解调器在不同事件之后发送未经请求的响应.当调制解调器改变注册状态(与蜂窝塔一起)时,它将响应+CGREG: 1, ...
GPS或准备就绪时GPS Ready
.这些响应可以随时发生,包括在命令中间(如创建IP连接).
这是一个问题,因为我没有想过要解决这个问题的方法.我的应用程序需要发送命令(例如,连接到服务器AT+CIPSTART="UDP","example.com",5000
),此命令将以"OK"响应,然后当命令完成"CONNECT OK"时.但是,我需要能够对许多其他可能的响应作出反应,而我还没有找到一种方法.我的代码需要做什么; 等待来自调制解调器的响应,检查响应,根据该响应执行操作?
我是代码有限的(是一个8位微控制器!),并希望将重复保持在最低限度.如何编写响应函数,从GSM模块(征求或现在)获取响应,然后让我的程序的其余部分知道发生了什么?
理想情况下,我想对这些回复做些什么.就像保持一个内部状态(当我听到GPS Ready
,我知道我可以为GPS等供电
也许有一些我应该考虑的事情,或者可能有一个开源项目已经解决了这个问题?
这是我到目前为止所拥有的:
/* Command responses */
enum {
// Common
OK = 0,
ERROR,
TIMEOUT,
OTHER,
// CGREG
NOT_REGISTERED,
// CGATT
NOT_ATTACHED,
// Network Status
NO_NETWORK,
// GPRS status
NO_ADDRESS,
// HTTP ACTION
NETWORK_ERROR,
// IP Stack State
IP_INITIAL,
IP_STATUS,
IP_CONFIG,
UDP_CLOSING,
UDP_CLOSED,
UDP_CONNECTING
} gsmResponse;
int gsm_sendCommand(const char * cmd) {
unsigned long timeout = timer_getCurrentTime() …
Run Code Online (Sandbox Code Playgroud) 我有一些设计用于处理1-256字节的函数,在嵌入式C平台上运行,其中传递字节比传递int(一条指令对三条)更快更紧凑,编码它的首选方法是什么:
当系统忙时,预计函数的内环可能占处理器执行时间的15%-30%; 它有时会用于少量字节,有时用于大字节.该函数使用的内存芯片具有每事务开销,我更喜欢让我的内存访问函数在内部执行start-transaction/do-stuff/end-transaction序列.
最有效的代码是简单地接受unsigned char并将参数值0视为执行256字节的请求,依赖于调用者以避免任何意外尝试读取0字节.但这似乎有点危险.有其他人在嵌入式系统上处理过这些问题吗?他们是如何处理的?
编辑 该平台是PIC18Fxx(128K代码空间; 3.5K RAM),连接到SPI闪存芯片; 当预期较少时读取256个字节可能会超出PIC中的读缓冲区.写入256个字节而不是0将破坏闪存芯片中的数据.如果没有检查忙状态,PIC的SPI端口每12个指令时间限制为一个字节; 如果有人会慢一些.典型的写事务除了要接收的数据外还需要发送4个字节; 读取需要额外的字节用于"SPI周转"(访问SPI端口的最快方法是在发送下一个字节之前读取最后一个字节).
编译器是HiTech PICC-18std.
我一般都喜欢HiTech的PICC-16编译器; HiTech似乎已经将他们的能量从PICC-18std产品转移到他们的PICC-18pro系列,它的编译时间更慢,似乎需要使用3字节"const"指针而不是双字节指针,并且有它的关于内存分配的想法.也许我应该更多地看看PICC-18pro,但是当我尝试在一个版本的PICC-18pro上编译我的项目时,它没有用,我也没弄清楚为什么 - 也许是关于变量布局不同意的事情我的asm例程 - 我只是继续使用PICC-18std.
顺便说一句,我刚刚发现PICC-18特别喜欢do {} while( - bytevar); 特别不喜欢做{} while( - intvar); 我想知道编译器生成后者时会发生什么?
do { local_test++; --lpw; } while(lpw); 2533 ;newflashpic.c: 792: do 2534 ;newflashpic.c: 793: { 2535 0144A8 2AD9 incf fsr2l,f,c 2536 ;newflashpic.c: 795: } while(--lpw); 2537 0144AA 0E00 movlw low ?_var_test 2538 0144AC 6EE9 movwf fsr0l,c 2539 0144AE …
当我声明一个接受的函数const char*
并且我传递一个字符串文字时,我得到一个
警告:[2066]类型限定符在分配中不匹配
因为字符串文字是rom const char*
.反过来也是这样.
尽管PIC是哈佛架构,但内存被映射到一个连续的地址空间,因此理论上应该可以以相同的方式支持ram和rom指针.可能我必须使用rom指针,因为它们是24位而ram指针是16位.
但是,只是将a转换const char*
为a const rom char*
不起作用.
我将开始一个项目,我需要对PIC单片机的汇编语言有一个很好的理解.我非常熟悉C/C++,所以我知道如何编写代码,我已经为PIC做了很多项目,所以我理解了这个架构,但是在'C'中完成了我的所有编程.
是否有一本好书或网站能够很好地解释所有汇编命令的含义以及如何为PIc微控制器执行相当简单的任务(闪烁LED,基本数学等等)?
编辑:这篇文章的主要目的是请求学习汇编的资源,而不是在PIC中讨论C与汇编的优点,或者PIC是否是一个"好"的微控制器.我使用的是PIC18单片机,如果这有任何区别的话.
在编写PIC18时,如何创建并行运行的线程,因为没有操作系统?
这与微控制器有关,但考虑将其发布在此处,因为它是算法和数据类型的问题,而不是任何硬件内容.我将解释这个问题,以便没有任何硬件知识的人仍然可以参加:)
在微控制器中,有一个10位分辨率的模数转换器.(它将输出0到1023之间的值)
我需要使用串口将此值发送到PC.
但是你一次只能写8位.(你需要写字节).这是微控制器的一个限制.
所以在上面的情况下至少我需要发送2个字节.
我的PC应用程序只读取一系列数字用于绘图.所以它应该捕获两个连续的字节并重新构建数字.但是在这里我们也需要一个分隔符.但是分隔符字符的ascii值在0到255之间,那么它会混淆该过程.
那么最简单的方法是什么?我应该将值作为一系列字符发送吗?
Ex : 1023 = "1""0""2""3" Vs "Char(255)Char(4)"
Run Code Online (Sandbox Code Playgroud)
总之,我需要以最快的方式在Serial上发送一个10位数的序列.:)
我正在寻找适用于微芯片PIC32的解释语言.
目前,我发现LUA和PAWN正在工作,但在选择之前,我想知道是否已知某些其他语言在PIC32中工作.
我试图将NSA SPECK的实现安装在8位PIC微控制器中。他们的编译器的免费版本(基于CLANG)将无法进行优化,因此我的内存不足。我尝试了启用-O2,-O3和-Os(针对大小进行优化)的“试用版”。使用-Os可以使我的代码适合2K程序存储空间。
这是代码:
#include <stdint.h>
#include <string.h>
#define ROR(x, r) ((x >> r) | (x << (32 - r)))
#define ROL(x, r) ((x << r) | (x >> (32 - r)))
#define R(x, y, k) (x = ROR(x, 8), x += y, x ^= k, y = ROL(y, 3), y ^= x)
#define ROUNDS 27
void encrypt_block(uint32_t ct[2],
uint32_t const pt[2],
uint32_t const K[4]) {
uint32_t x = pt[0], y = pt[1];
uint32_t a = K[0], b = K[1], …
Run Code Online (Sandbox Code Playgroud) 我需要在地址 0xDD2 处调用一个函数:
// foo.h
void foo(void) __at(0xDD2);
// foo.c
#include "foo.h"
void foo(void)
{
// some code
}
Run Code Online (Sandbox Code Playgroud)
此代码有效:
#include "foo.h"
void main(void)
{
void (*a)(void) = &foo;
a();
}
Run Code Online (Sandbox Code Playgroud)
然而,这个没有:
#include "foo.h"
void main(void)
{
void (*a)(void) = (void (*)(void))(0x0DD2);
a();
}
Run Code Online (Sandbox Code Playgroud)
编译器 (XC8) 说:main.c:5:: warning: (759) expression generates no code
调试器在调试时传递这些行。
我需要第二个(仅通过其地址调用函数)。为什么编译器会优化它?指针赋值有没有错误?更改编译器的优化级别没有帮助。