Pergunta

Estou construindo um pequeno dispositivo com a sua própria CPU (AVR Mega8) que é suposto para conectar a um PC. Assumindo que a conexão física e passando de bytes foi realizado, o que seria o melhor protocolo a ser usado em cima desses bytes? As necessidades de computador para ser capaz de definir certas tensões no dispositivo, e ler algumas outras tensões.

No momento, estou pensando um protocolo síncrono completamente orientada para o host: pedidos computador de envio, as respostas CPU embarcadas. Quaisquer outras ideias?

Foi útil?

Solução

Modbus pode ser o que você está procurando. Ele foi projetado para exatamente o tipo de problema que você tem. Há lotes de código / ferramentas lá fora e adesão a um padrão poderia significar fácil reutilização posterior. Ele também suporta ASCII legível por isso ainda é fácil de entender / teste.

FreeModBus para janelas e fonte incorporado.

Outras dicas

Há muito a ser dito para a arquitetura cliente-servidor e protocolos síncronos. Simplicidade e robustez, para começar. Se a velocidade não é um problema, você pode considerar um protocolo compacto, legível para ajudar com a depuração. Estou pensando ao longo das linhas de modem AT comandos:. Uma sequência "despertar" seguido por um set / get comando, seguido por um terminador

Host -->  [V02?]      // Request voltage #2
AVR  -->  [V02=2.34]  // Reply with voltage #2
Host -->  [V06=3.12]  // Set voltage #6
AVR  -->  [V06=3.15]  // Reply with voltage #6

Cada lado pode expirar se ele não vê o colchete de fechamento, e eles re-sincronizar na próxima suporte aberto, o que não pode aparecer dentro da própria mensagem.

Dependendo dos requisitos de velocidade e confiabilidade, você pode codificar os comandos em um ou dois bytes e adicionar uma soma de verificação.

É sempre uma boa idéia para responder com o real tensão, em vez de simplesmente ecoando o comando, uma vez que poupa uma operação de leitura posterior.

Também útil para definir mensagens de erro, em caso de necessidade de depuração.

Meu voto é para a leitura humana.

Mas se você for binário, tentar colocar um byte de cabeçalho no início para marcar o início de um pacote. Eu sempre tive má sorte com protocolos seriais ficar fora de sincronia. O byte do cabeçalho permite que o sistema embarcado para re-sincronização com o PC. Além disso, adicionar um checksum no final.

Já fiz coisas como esta com um formato binário simples

struct PacketHdr
{
  char syncByte1;
  char syncByte2;
  char packetType;
  char bytesToFollow;  //-or- totalPacketSize
};

struct VoltageSet
{ 
   struct PacketHdr;
   int16 channelId;
   int16 voltageLevel; 
   uint16 crc;
};

struct VoltageResponse
{
   struct PacketHdr;
   int16 data[N];  //Num channels are fixed
   uint16 crc;
}

Os bytes de sincronização são menos críticos em um protocolo síncrono do que em um um assíncrono, mas eles ainda ajuda, especialmente quando o sistema embarcado é primeiro ligar, e você não sabe se o primeiro byte ele recebe é o meio de uma mensagem ou não.

O tipo deve ser um enum que diz como interpretar que o pacote. Tamanho pode ser inferida a partir de tipo, mas se você enviá-lo explicitamente, em seguida, o receptor pode lidar com tipos desconhecidos sem engasgar. Você pode usar 'tamanho total do pacote', ou 'bytes a seguir'; este último pode tornar o código receptor um pouco de.

O CRC no final adiciona mais garantia de que você tem dados válidos. Às vezes eu vi o CRC no cabeçalho, o que torna declarando estruturas mais fácil, mas colocá-lo no final permite-lhe evitar uma passagem extra sobre os dados ao enviar a mensagem.

O remetente eo receptor devem ambos têm tempos de espera iniciado imediatamente após o primeiro byte de um pacote é recebido, no caso de um byte é descartado. O lado PC também precisa de um tempo limite para lidar com o caso quando o sistema integrado não está conectado e não houver nenhuma resposta em tudo.

Se você tem certeza de que ambas as plataformas usar IEEE-754 floats (PC fazer) e têm a mesma ordenação, então você pode usar carros alegóricos como o tipo de dados. Caso contrário, é mais seguro de usar números inteiros, quer bits de A / D-primas, ou uma escala predefinida (i.e. um pouco = .001V dá um intervalo de +/- 32,267 V)

Adam Liss faz um monte de grandes pontos. Simplicidade e robustez deve ser o foco. transferências ASCII legível ajudar muito enquanto depuração. Ótimas sugestões.

Eles podem ser um exagero para as suas necessidades, mas HDLC e / ou PPP add no conceito de uma camada de enlace de dados, e todos os benefícios (e custos) que vêm com uma camada de enlace de dados. Gerenciamento de links, enquadramento, somas de verificação, os números de seqüência, re-transmissões, etc ... tudo isso ajuda a garantir comunicações robustas, mas adiciona complexidade, processamento e tamanho do código, e pode não ser necessário para a sua aplicação particular.

USB irá responder a todas as suas necessidades. Pode ser um dispositivo USB muito simples, com apenas tubo de controle para enviar pedido para o seu dispositivo ou você pode adicionar um tubo de interrupção que lhe permitirá notificar hospedeiro com alterações no seu dispositivo. Há um número de simples controladores USB que podem ser usadas, por exemplo Cypress ou Microchip .

Protocolo no topo da transferência é realmente sobre suas necessidades. De sua descrição parece que o protocolo síncrono simples é definitivamente o suficiente. O que faz você passear e olhar para a abordagem adicional? Compartilhe suas dúvidas e vamos tentar ajudar :).

Se eu não estava esperando a necessidade de fazer transferências binários eficientes, eu iria para a interface de estilo terminal já sugerido.

Se eu quero fazer um formato de pacote binário, que tendem a usar algo vagamente baseado no PPP byte-asnc formato HDLC, que é extremamente simples e fácil de enviar receber, basicamente:

Os pacotes começam e terminam com 0x7e Está escapar um char pré-fixando com 0x7D e alternando o bit 5 (isto é, xor com 0x20) Então 0x7e se torna 0x5e 0x7D e 0x7D se torna 0x7D 0x5D

Cada vez que você vê um 0x7e em seguida, se você tem todos os dados armazenados, você pode processá-lo.

Eu costumo fazer coisas síncrona impulsionado-host a menos que tenha uma boa razão para fazer o contrário. É uma técnica que se estende desde RS232 ponto-ponto simples de Multidrop RS422 / 485, sem pressa -. Geralmente um bônus

Como você pode já ter determinado a partir de todas as respostas não dirigir diretamente a um protocolo, que um rolo de sua própria abordagem para ser sua melhor escolha.

Então, isso me fez pensar e bem, aqui estão alguns dos meus pensamentos -

Tendo em conta que este chip tem 6 canais ADC, o mais provável que você está usando RS-232 comm de série (um palpite da sua pergunta), e, claro, o espaço de código limitado, a definição de uma estrutura de comando simples vai ajudar, como Adam aponta - você pode querer manter o processamento de entrada a um mínimo do chip, sons tão binários atraente, mas o off trade está na facilidade de desenvolvimento e manutenção (você pode ter que atirar problemas uma entrada morto 6 meses a partir de agora) - hyperterminal é uma ferramenta de depuração poderoso -. então, isso me fez pensar de como implementar uma estrutura de comando simples, com boa confiabilidade

Algumas considerações gerais -

keep comandos do mesmo tamanho -. Torna mais fácil decodificação

Framing os comandos e soma de verificação opcional, como Adam aponta pode ser facilmente envolvida em torno de seus comandos. (Com comandos pequenas, uma simples soma de verificação XOR / ADD é rápido e indolor)

Eu recomendaria um anúncio de arranque para o anfitrião com a versão do firmware na redefinição - por exemplo, "OLÁ; Firmware Versão 1.00z." - diria o host que o alvo apenas começou e que está funcionando

Se você estiver monitorando principalmente, você pode querer considerar um modo de "free run" onde o alvo seria simplesmente percorrer o analógico e leituras digitais - é claro, isso não tem que ser contínua, pode ser espaçadas em 1, 5, 10 segundos, ou apenas no comando. Seu micro está sempre ouvindo assim o envio de um valor atualizado é uma tarefa independente.

terminação cada linha de saída com um CR (ou outro carácter) faz sincronização no hospedeiro para a frente.

por exemplo, o micro poderia simplesmente saída das cordas;

  V0=3.20
  V1=3.21
  V2= ...
  D1=0
  D2=1
  D3=...
  and then start over -- 

Além disso, os comandos podem ser muito simples -

? - Leia todos os valores -. Não há que muitos deles, então levá-los todos

X = 12,34 - "" Para definir um valor, o primeiro byte é a porta, então a tensão e eu recomendaria mantendo o "=" eo como enquadramento para assegurar um pacote válido se você renunciar a soma de verificação.

Outra possibilidade, se as suas saídas estão dentro de um intervalo definido, você pode pré-escala-los. Por exemplo, se a saída não tem que ser exato, você poderia enviar algo como

5=0 
6=9
2=5  

que iria definir port 5 off, porta 6 a full on e porta 2 a metade valor - Com esta abordagem, ascii e dados binários são apenas sobre em pé de igualdade no que diz respeito à computação / decodificação de recursos no micro. Ou para mais precisão, fazer a saída 2 bytes, por exemplo, 2 = 54 - OR, adicione uma tabela de referência externa e os valores nem sequer tem que ser linear, onde o byte de dados é um índice em uma tabela look-up .. .

Como eu gosto de dizer; simples é geralmente melhor, a menos que ele não é.

Espero que isso ajude um pouco.


Tinha outro pensamento enquanto re-leitura; adicionar um comando "*" pode solicitar os dados envolvidas com html tags e agora seu aplicativo anfitrião poderia simplesmente redirecionar a saída de seu micro para um navegador e wala, navegador pronto -

:)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top