передача массива в порт и подсчёт контрольной суммы

alexval2007
Offline
Зарегистрирован: 10.11.2012

добрый день возникла проблема с передачей данных в последовательный порт из массива с подсчётом контрольной суммы посылки вобщем обясню на примерах

в идеале должно быть так на запрос получаем ответ смотрите ниже

//запросм
01 01 02 02 D0 B9

//ответ
01 01 1D AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA CB 91

на данны момент вожусь с отправкой ответа до сюда все нормально если без контрольной суммы

01 01 1D AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA

контрольная сумма для этой посылки должна быть CB 91

а вот что получается если отправлять с контрольной суммой

01 01 1D AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA CB 00

последний байт контрольной суммы почемуто нулевой а должен быть 91

код

/*
   termo_atmega328p
   Version: 1.0.0.0
   Release: 16.08.2017
*/
//---------------------------------------------------------------------------
// Подключаем библиотеки:
#include <Keypad.h>
//---------------------------------------------------------------------------
#define MaxLenghtTrBuf   33 //размер буфера передаваемых по UART данных
#define Hi(int) (byte) (int>>8)
#define Low(int) (byte) (int)
#define time_Key_ask    10    //
#define USART_USB_RATE  9600  //  
#define TX_RX_pin  2  
//---------------------------------------------------------------------------
byte CRC16;
unsigned int Adress = 0;   // 
char key;
char Last_Key = 0;
unsigned char KpdState = 0;
unsigned long msNow = 0;
unsigned long time_Key = 0;
//---------------------------------------------------------------------------
const byte ROWS = 4; // 4 строки
const byte COLS = 4; // 4 столбца

char keys[ROWS][COLS] = 
{
  {'1','2','3','A',},
  {'4','5','6','B',},
  {'7','8','9','C',},
  {'*','0','#','D' }
};

// Строки клавиатуры ROW0, ROW1, ROW2 и ROW3. Подключение к контактам Arduino.
byte rowPins[ROWS] = {3, 4, 6, 7};//
// Столбцы клавиатуры COL0, COL1, COL2 и COL3. Подключение к контактам Arduino.
byte colPins[COLS] = {8, 10, 11, 12};// 
// Создадим клавиатуру
Keypad kpd = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
//---------------------------------------------------------------------------
void Key_Ask();
unsigned int GetCRC16(byte *buf, byte bufsize);
//---------------------------------------------------------------------------
byte cmTrBuf1[MaxLenghtTrBuf];  //буфер передаваемых данных
//массивы для быстрого расчета кода CRC-16
byte srCRCHi[256]={
         0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
         0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
         0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
         0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
         0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
         0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
         0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
         0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
         0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
         0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
         0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
         0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
         0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
         0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
         0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
         0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
         0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
         0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
         0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
         0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
         0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
         0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
         0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
         0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
         0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
         0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
};
 byte srCRCLo[256]={
         0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
         0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
         0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
         0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
         0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
         0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
         0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
         0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
         0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
         0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
         0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
         0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
         0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
         0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
         0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
         0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
         0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
         0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
         0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
         0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
         0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
         0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
         0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
         0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
         0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
         0x43, 0x83, 0x41, 0x81, 0x80, 0x40
};
//---------------------------------------------------------------------------
void Key_Ask()
{
  time_Key = millis() + time_Key_ask;
  key = kpd.getKey();
       
  if(key) Last_Key = key; // тоже самое что if(key != NO_KEY)
  KpdState = kpd.getState();
  if(2 == kpd.getState()) Last_Key = 'N'; 
  switch (key)
  {
    case 'D': Adress = 1; Last_Key = 'N'; break; //ВЫБОР     
  }     

 if(Adress != 0) //если адрес подвески < 0 тогда отправляем запрос в порт.
 {
   byte calculated_crc=0;
   byte n=0; 
   //Отправка температуры    
   digitalWrite(TX_RX_pin, HIGH); //включаем передачу по rs485
   cmTrBuf1[0]=Adress;//системный номер устройсва
   cmTrBuf1[1]=0x01;//команда (Чтение данных измерения) чтение температуры
   cmTrBuf1[2]=0x1D;//количесво байт данных
   
   cmTrBuf1[3]=0xAA;//данные температуры
   cmTrBuf1[4]=0xAA;//данные температуры
   cmTrBuf1[5]=0xAA;//данные температуры
   cmTrBuf1[6]=0xAA;//данные температуры
   cmTrBuf1[7]=0xAA;//данные температуры
   cmTrBuf1[8]=0xAA;//данные температуры
   cmTrBuf1[9]=0xAA;//данные температуры
   cmTrBuf1[10]=0xAA;//данные температуры
   cmTrBuf1[11]=0xAA;//данные температуры
   cmTrBuf1[12]=0xAA;//данные температуры
   cmTrBuf1[13]=0xAA;//данные температуры
   cmTrBuf1[14]=0xAA;//данные температуры
   cmTrBuf1[15]=0xAA;//данные температуры
   cmTrBuf1[16]=0xAA;//данные температуры
   cmTrBuf1[17]=0xAA;//данные температуры
   cmTrBuf1[18]=0xAA;//данные температуры
   cmTrBuf1[19]=0xAA;//данные температуры
   cmTrBuf1[20]=0xAA;//данные температуры
   cmTrBuf1[21]=0xAA;//данные температуры
   cmTrBuf1[22]=0xAA;//данные температуры
   cmTrBuf1[23]=0xAA;//данные температуры
   cmTrBuf1[24]=0xAA;//данные температуры
   cmTrBuf1[25]=0xAA;//данные температуры
   cmTrBuf1[26]=0xAA;//данные температуры
   cmTrBuf1[27]=0xAA;//данные температуры
   cmTrBuf1[28]=0xAA;//данные температуры
   cmTrBuf1[29]=0xAA;//данные температуры
   cmTrBuf1[30]=0xAA;//данные температуры
   
   n = cmTrBuf1[2];//количесво байт данных
   n = n + 2;//кол-во передаваемых байт без CRC
   calculated_crc = GetCRC16(cmTrBuf1, n);//подсчет КС посылки
   cmTrBuf1[n++] = Low(calculated_crc);//Контрольная сумма младший байт
   cmTrBuf1[n++] = Hi(calculated_crc); //Контрольная сумма старший байт
   
   for (int j = 0; j < n; j++)//В цикле выводим данные в порт
   {
     Serial.write(cmTrBuf1[j]);
   }
   delay(50);//время для передачи посылки
   digitalWrite(TX_RX_pin, LOW); //включаем приём по rs485   
   Adress = 0;
 }   
}
//-----------------------------------------------------------------
//функция вычисляет код CRC-16 на входе указатель на начало 
//буфера и количество байт сообщения (без принятого кода CRC-16)
unsigned int GetCRC16(byte *buf, byte bufsize)
{
  byte CRC_Low = 0xFF;
  byte CRC_High = 0xFF;
  byte k;
  byte carry;
  for (k = 0; k < bufsize; k++)
   {
    carry = CRC_Low ^ buf[k];
    CRC_Low = CRC_High ^ srCRCHi[carry];
    CRC_High = srCRCLo[carry];
   };
  return((CRC_High << 8)|CRC_Low);
}//end GetCRC16()
//**********************************************************
void setup() 
{
  pinMode(TX_RX_pin, OUTPUT);  // ножка управления режимом RX/TX RS485
  Serial.begin(USART_USB_RATE, SERIAL_8E1);//инициализация UART
  kpd.setHoldTime (20);        // 
  kpd.setDebounceTime (10);    // задержка от дребезга
}
//---------------------------------------------------------------------------
void loop() 
{
  msNow = millis(); 
  if (time_Key < msNow) Key_Ask();//циклический опрос клавиатуры по времени
}
//---------------------------------------------------------------------------

 

alexval2007
Offline
Зарегистрирован: 10.11.2012

так как мне неудалось добится нормальной работы от преведущего варианта кода попроюовал заменить функцию вычесления контрольной суммы на другую вот что из этого получилось, работает стабильно мусора в порт неотправляет.

В порт шлёт 01 01 1D AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA CB 91

то что и должно было слать. Так и непонял почему неработает табличная функция вычисления контрольной суммы она быстрее должна работать.

/*
   Termo_atmega328p
   Version: 2.0.0.0
   Release: 17.08.2017
*/
//---------------------------------------------------------------------------
// Подключаем библиотеки:
#include <Keypad.h>
//---------------------------------------------------------------------------
#define MaxLenghtTrBuf   39 //размер буфера передаваемых по UART данных
#define Hi(char) (byte) (char >> 8)
#define Low(char) (byte) (char)
#define time_Key_ask    10    //
#define USART_USB_RATE  9600  //  
#define TX_RX_pin  2  
//---------------------------------------------------------------------------
unsigned int Adress = 0;   // 
char key;
char Last_Key = 0;
unsigned char KpdState = 0;
unsigned long msNow = 0;
unsigned long time_Key = 0;
int response_length;
unsigned int crc_calc = 0;
//---------------------------------------------------------------------------
const byte ROWS = 4; // 4 строки
const byte COLS = 4; // 4 столбца

char keys[ROWS][COLS] = 
{
  {'1','2','3','A',},
  {'4','5','6','B',},
  {'7','8','9','C',},
  {'*','0','#','D' }
};

// Строки клавиатуры ROW0, ROW1, ROW2 и ROW3. Подключение к контактам Arduino.
byte rowPins[ROWS] = {3, 4, 6, 7};//
// Столбцы клавиатуры COL0, COL1, COL2 и COL3. Подключение к контактам Arduino.
byte colPins[COLS] = {8, 10, 11, 12};// 
// Создадим клавиатуру
Keypad kpd = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
//---------------------------------------------------------------------------
void Key_Ask();
//---------------------------------------------------------------------------
byte cmTrBuf1[MaxLenghtTrBuf];  //буфер передаваемых данных
unsigned int crc(unsigned char *buf, unsigned char cnt);
//---------------------------------------------------------------------------
void Key_Ask()
{
  time_Key = millis() + time_Key_ask;
  key = kpd.getKey();
       
  if(key) Last_Key = key; // тоже самое что if(key != NO_KEY)
  KpdState = kpd.getState();
  if(2 == kpd.getState()) Last_Key = 'N'; 
  switch (key)
  {
    case 'D': Adress = 1; Last_Key = 'N'; break; //ВЫБОР     
  }     

 if(Adress != 0) //если адрес подвески < 0 тогда отправляем запрос в порт.
 {
   byte calculated_crc=0;
   byte n=0; 
   //Отправка температуры    
   digitalWrite(TX_RX_pin, HIGH); //включаем передачу по rs485
   cmTrBuf1[0]=Adress;//системный номер устройсва
   cmTrBuf1[1]=0x01;//команда (Чтение данных измерения) чтение температуры
   cmTrBuf1[2]=0x1D;//количесво байт данных
   
   cmTrBuf1[3]=0xAA;//данные температуры
   cmTrBuf1[4]=0xAA;//данные температуры
   cmTrBuf1[5]=0xAA;//данные температуры
   cmTrBuf1[6]=0xAA;//данные температуры
   cmTrBuf1[7]=0xAA;//данные температуры
   cmTrBuf1[8]=0xAA;//данные температуры
   cmTrBuf1[9]=0xAA;//данные температуры
   cmTrBuf1[10]=0xAA;//данные температуры
   cmTrBuf1[11]=0xAA;//данные температуры
   cmTrBuf1[12]=0xAA;//данные температуры
   cmTrBuf1[13]=0xAA;//данные температуры
   cmTrBuf1[14]=0xAA;//данные температуры
   cmTrBuf1[15]=0xAA;//данные температуры
   cmTrBuf1[16]=0xAA;//данные температуры
   cmTrBuf1[17]=0xAA;//данные температуры
   cmTrBuf1[18]=0xAA;//данные температуры
   cmTrBuf1[19]=0xAA;//данные температуры
   cmTrBuf1[20]=0xAA;//данные температуры
   cmTrBuf1[21]=0xAA;//данные температуры
   cmTrBuf1[22]=0xAA;//данные температуры
   cmTrBuf1[23]=0xAA;//данные температуры
   cmTrBuf1[24]=0xAA;//данные температуры
   cmTrBuf1[25]=0xAA;//данные температуры
   cmTrBuf1[26]=0xAA;//данные температуры
   cmTrBuf1[27]=0xAA;//данные температуры
   cmTrBuf1[28]=0xAA;//данные температуры
   cmTrBuf1[29]=0xAA;//данные температуры
   cmTrBuf1[30]=0xAA;//данные температуры
   
   n = cmTrBuf1[2];//количесво байт данных
   response_length = n + 2;//кол-во передаваемых байт без CRC
   crc_calc = crc(cmTrBuf1, response_length);
   cmTrBuf1[response_length++] = Hi(crc_calc);//Контрольная сумма младший байт
   cmTrBuf1[response_length++] = Low(crc_calc); //Контрольная сумма старший байт
   
   for (int j = 0; j < response_length; j++)//В цикле выводим данные в порт
   {
     Serial.write(cmTrBuf1[j]);
   }
   delay(50);//время для передачи посылки
   digitalWrite(TX_RX_pin, LOW); //включаем приём по rs485   
   Adress = 0;
 }   
}
//-----------------------------------------------------------------
//функция вычисляет код CRC-16 на входе указатель на начало 
//буфера и количество байт сообщения (без принятого кода CRC-16)
// Входные переменные:
//  buf   ->  Массив, содержащий сообщение, которое будет отправлено на контроллер.            
//  cnt   ->  Количество байтов в сообщении
// Возвращяет:
//  temp  ->  Возвращяет КС.
// Коментарий:
//  Эта процедура вычисляет старший байт КС и младший байт КС.
//-----------------------------------------------------------------------
unsigned int crc(unsigned char *buf, unsigned char cnt) 
{
        unsigned char start=0;
        unsigned char i, j;
        unsigned temp, temp2, flag;
        temp = 0xFFFF;
        for (i = start; i < cnt; i++) 
        {
           temp = temp ^ buf[i];
           for (j = 1; j <= 8; j++) 
           {
              flag = temp & 0x0001;
              temp = temp >> 1;
              if (flag) temp = temp ^ 0xA001;
           }
        }

        //обратный порядок байт
        temp2 = temp >> 8;
        temp = (temp << 8) | temp2;
        temp &= 0xFFFF;
        return (temp);
} 
//---------------------------------------------------------------------------
void setup() 
{
  pinMode(TX_RX_pin, OUTPUT);  // ножка управления режимом RX/TX RS485
  Serial.begin(USART_USB_RATE, SERIAL_8E1);//инициализация UART
  kpd.setHoldTime (20);        // 
  kpd.setDebounceTime (10);    // задержка от дребезга
}
//---------------------------------------------------------------------------
void loop() 
{
  msNow = millis(); 
  if (time_Key < msNow) Key_Ask();//циклический опрос клавиатуры по времени
}
//---------------------------------------------------------------------------