Compare commits

..

2 Commits

Author SHA1 Message Date
f5210ce050 подправлены внешний вид и коменты 2025-08-31 14:27:25 +03:00
ef623e8b0b +freertos
но надо еще коменты подправить
2025-08-31 13:24:11 +03:00
8 changed files with 1200 additions and 1145 deletions

View File

@ -1,9 +1,13 @@
#include "rs_message.h" #include "rs_message.h"
#include "FreeRTOS.h"
void setup() { void setup() {
// put your setup code here, to run once: // put your setup code here, to run once:
MODBUS_FirstInit(); MODBUS_FirstInit();
//hmodbus1.RS_STATUS = RS_Init(&hmodbus1, &rs_huart, MB_SPEED, 0);
xTaskCreatePinnedToCore(RS_Task, "Modbus", 4096, &hmodbus1, 2, NULL, 1);
Serial.begin(115200); // для отладки Serial.begin(115200); // для отладки
Serial.println("start"); Serial.println("start");
@ -11,9 +15,5 @@ void setup() {
} }
void loop() { void loop() {
// put your main code here, to run repeatedly: //RS_Process(&hmodbus1);
RS_Process(&hmodbus1); }
//delay(500);
//Serial.println("start");
//rs_huart.println("start1");
}

View File

@ -1,4 +1,4 @@
#include "crc_algs.h" #include "modbus/crc_algs.h"
uint32_t CRC_calc; uint32_t CRC_calc;
@ -16,40 +16,40 @@ unsigned uIndex;
uint32_t crc32(uint8_t *data, uint32_t data_size) uint32_t crc32(uint8_t *data, uint32_t data_size)
{ {
static const unsigned int crc32_table[] = static const unsigned int crc32_table[] =
{ {
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
}; };
unsigned int crc = 0xFFFFFFFF; unsigned int crc = 0xFFFFFFFF;
while (data_size--) while (data_size--)
@ -62,55 +62,55 @@ unsigned int crc = 0xFFFFFFFF;
uint16_t crc16(uint8_t *data, uint32_t data_size) uint16_t crc16(uint8_t *data, uint32_t data_size)
{ {
/*Table of CRC values for high order byte*/ /*Table of CRC values for high order byte*/
static unsigned char auchCRCHi[]= static unsigned char auchCRCHi[]=
{ {
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,
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, 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,
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,
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,
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, 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, 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,
}; };
/*Table of CRC values for low order byte*/ /*Table of CRC values for low order byte*/
static char auchCRCLo[] = static char auchCRCLo[] =
{ {
0x00,0xC0,0xC1,0x01,0xC3,0x03,0x02,0xC2,0xC6,0x06,0x07,0xC7,0x05,0xC5,0xC4,0x04, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 0x44,0x84,0x85,0x45,0x87,0x47,0x46,0x86,0x82,0x42,0x43,0x83,0x41,0x81,0x80,0x40,
}; };
uchCRCHi = 0xFF; uchCRCHi = 0xFF;
uchCRCLo = 0xFF; uchCRCLo = 0xFF;
/* CRC Generation Function */ /* CRC Generation Function */
while( data_size--) /* pass through message buffer */ while( data_size--) /* pass through message buffer */
{ {
uIndex = uchCRCHi ^ *data++; /* calculate the CRC */ uIndex = uchCRCHi ^ *data++; /* calculate the CRC */
uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex]; uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex];
uchCRCLo = auchCRCLo[uIndex]; uchCRCLo = auchCRCLo[uIndex];
} }
return uchCRCHi | uchCRCLo<<8; return uchCRCHi | uchCRCLo<<8;
} }

1384
modbus.cpp

File diff suppressed because it is too large Load Diff

386
modbus.h
View File

@ -1,105 +1,99 @@
/** /**
************************************************************************** **************************************************************************
* @file modbus.h * @file modbus.h
* @brief Заголовочный файл модуля MODBUS. * @brief Заголовочный файл модуля MODBUS.
* @details Данный файл необходимо подключить в rs_message.h. После подключать * @details Данный файл необходимо подключить в rs_message.h. После подключать
* rs_message.h к основному проекту. * rs_message.h к основному проекту.
* *
* @defgroup MODBUS * @defgroup MODBUS
* @brief Modbus stuff * @brief Modbus stuff
* *
*************************************************************************/ *************************************************************************/
#ifndef __MODBUS_H_ #ifndef __MODBUS_H_
#define __MODBUS_H_ #define __MODBUS_H_
#include "modbus_config.h" #include "modbus/modbus_config.h"
#include "modbus_data.h" #include "modbus/modbus_data.h"
//#include "settings.h" // for modbus settings
/** /**
* @addtogroup MODBUS_SETTINGS * @addtogroup MODBUS_SETTINGS
* @ingroup MODBUS * @ingroup MODBUS
* @brief Some defines for modbus * @brief Some defines for modbus
@{ @{
*/ */
/////////////////////////////////////////////////////////////////////
//////////////////////////---SETTINGS---/////////////////////////////
// USER SETTINGS FOR MODBUS IN interface_config.h
//////////////////////////---SETTINGS---/////////////////////////////
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
/////////////////////---USER MESSAGE DEFINES---////////////////////// /////////////////////---USER MESSAGE DEFINES---//////////////////////
//-------------DEFINES FOR STRUCTURE---------------- //-------------DEFINES FOR STRUCTURE----------------
/* defines for structure of modbus message */ /* defines for structure of modbus message */
#define MbAddr_SIZE 1 ///< size of (MbAddr) #define MbAddr_SIZE 1 ///< size of (MbAddr)
#define Func_Code_SIZE 1 ///< size of (Func_Code) #define Func_Code_SIZE 1 ///< size of (Func_Code)
#define Addr_SIZE 2 ///< size of (Addr) #define Addr_SIZE 2 ///< size of (Addr)
#define Qnt_SIZE 2 ///< size of (Qnt) #define Qnt_SIZE 2 ///< size of (Qnt)
#define ByteCnt_SIZE 1 ///< size of (ByteCnt) #define ByteCnt_SIZE 1 ///< size of (ByteCnt)
#define DATA_SIZE 125 ///< maximum number of data: DWORD (NOT MESSAGE SIZE) #define DATA_SIZE 125 ///< maximum number of data: DWORD (NOT MESSAGE SIZE)
#define CRC_SIZE 2 ///< size of (MB_CRC) in bytes #define CRC_SIZE 2 ///< size of (MB_CRC) in bytes
/** @brief Size of whole message */ /** @brief Size of whole message */
#define INFO_SIZE_MAX (MbAddr_SIZE+Func_Code_SIZE+Addr_SIZE+Qnt_SIZE+ByteCnt_SIZE) #define INFO_SIZE_MAX (MbAddr_SIZE+Func_Code_SIZE+Addr_SIZE+Qnt_SIZE+ByteCnt_SIZE)
/** @brief Size of first part of message that will be received /** @brief Size of first part of message that will be received
first receive info part of message, than defines size of rest message*/ first receive info part of message, than defines size of rest message*/
#define RX_FIRST_PART_SIZE INFO_SIZE_MAX #define RX_FIRST_PART_SIZE INFO_SIZE_MAX
/** @brief Size of buffer: max size of whole message */ /** @brief Size of buffer: max size of whole message */
#define MSG_SIZE_MAX (INFO_SIZE_MAX + DATA_SIZE*2 + CRC_SIZE) // max possible size of message #define MSG_SIZE_MAX (INFO_SIZE_MAX + DATA_SIZE*2 + CRC_SIZE) // max possible size of message
/** @brief Structure for modbus exception codes */ /** @brief Structure for modbus exception codes */
typedef enum //MB_ExceptionTypeDef typedef enum //MB_ExceptionTypeDef
{ {
// reading // reading
NO_ERRORS = 0x00, ///< no errors NO_ERRORS = 0x00, ///< no errors
ILLEGAL_FUNCTION = 0x01, ///< Принятый код функции не может быть обработан ILLEGAL_FUNCTION = 0x01, ///< Принятый код функции не может быть обработан
ILLEGAL_DATA_ADDRESS = 0x02, ///< Адрес данных, указанный в запросе, недоступен ILLEGAL_DATA_ADDRESS = 0x02, ///< Адрес данных, указанный в запросе, недоступен
ILLEGAL_DATA_VALUE = 0x03, ///< Значение, содержащееся в поле данных запроса, является недопустимой величиной ILLEGAL_DATA_VALUE = 0x03, ///< Значение, содержащееся в поле данных запроса, является недопустимой величиной
SLAVE_DEVICE_FAILURE = 0x04, ///< Невосстанавливаемая ошибка имела место, пока ведомое устройство пыталось выполнить затребованное действие SLAVE_DEVICE_FAILURE = 0x04, ///< Невосстанавливаемая ошибка имела место, пока ведомое устройство пыталось выполнить затребованное действие
// ACKNOWLEDGE = 0x05, ///< idk // ACKNOWLEDGE = 0x05, ///< idk
// SLAVE_DEVICE_BUSY = 0x06, ///< idk // SLAVE_DEVICE_BUSY = 0x06, ///< idk
// MEMORY_PARITY_ERROR = 0x08, ///< idk // MEMORY_PARITY_ERROR = 0x08, ///< idk
}MB_ExceptionTypeDef; }MB_ExceptionTypeDef;
#define ERR_VALUES_START 0x80U ///< from this value starts error func codes #define ERR_VALUES_START 0x80U ///< from this value starts error func codes
/** @brief Structure for modbus func codes */ /** @brief Structure for modbus func codes */
typedef enum //MB_FunctonTypeDef typedef enum //MB_FunctonTypeDef
{ {
/* COMMANDS */ /* COMMANDS */
// reading // reading
MB_R_COILS = 0x01, ///< Чтение битовых ячеек MB_R_COILS = 0x01, ///< Чтение битовых ячеек
MB_R_DISC_IN = 0x02, ///< Чтение дискретных входов MB_R_DISC_IN = 0x02, ///< Чтение дискретных входов
#ifndef MODBUS_SWITCH_COMMAND_R_IN_REGS_AND_R_HOLD_REGS #ifndef MODBUS_SWITCH_COMMAND_R_IN_REGS_AND_R_HOLD_REGS
MB_R_HOLD_REGS = 0x03, ///< Чтение входных регистров MB_R_HOLD_REGS = 0x03, ///< Чтение входных регистров
MB_R_IN_REGS = 0x04, ///< Чтение регистров хранения MB_R_IN_REGS = 0x04, ///< Чтение регистров хранения
#else #else
MB_R_HOLD_REGS = 0x04, ///< Чтение входных регистров MB_R_HOLD_REGS = 0x04, ///< Чтение входных регистров
MB_R_IN_REGS = 0x03, ///< Чтение регистров хранения MB_R_IN_REGS = 0x03, ///< Чтение регистров хранения
#endif #endif
// writting
MB_W_COIL = 0x05, ///< Запись битовой ячейки
MB_W_HOLD_REG = 0x06, ///< Запись одиночного регистра
MB_W_COILS = 0x0F, ///< Запись нескольких битовых ячеек
MB_W_HOLD_REGS = 0x10, ///< Запись нескольких регистров
MB_R_DEVICE_INFO = 0x2B, ///< Чтения информации об устройстве // writting
MB_W_COIL = 0x05, ///< Запись битовой ячейки
MB_W_HOLD_REG = 0x06, ///< Запись одиночного регистра
MB_W_COILS = 0x0F, ///< Запись нескольких битовых ячеек
MB_W_HOLD_REGS = 0x10, ///< Запись нескольких регистров
MB_R_DEVICE_INFO = 0x2B, ///< Чтения информации об устройстве
/* ERRORS */ /* ERRORS */
// error reading // error reading
MB_ERR_R_COILS = MB_R_COILS + ERR_VALUES_START, ///< Ошибка чтения битовых ячеек MB_ERR_R_COILS = MB_R_COILS + ERR_VALUES_START, ///< Ошибка чтения битовых ячеек
MB_ERR_R_DISC_IN = MB_R_DISC_IN + ERR_VALUES_START, ///< Ошибка чтения дискретных входов MB_ERR_R_DISC_IN = MB_R_DISC_IN + ERR_VALUES_START, ///< Ошибка чтения дискретных входов
MB_ERR_R_IN_REGS = MB_R_IN_REGS + ERR_VALUES_START, ///< Ошибка чтения регистров хранения MB_ERR_R_IN_REGS = MB_R_IN_REGS + ERR_VALUES_START, ///< Ошибка чтения регистров хранения
MB_ERR_R_HOLD_REGS = MB_R_HOLD_REGS + ERR_VALUES_START, ///< Ошибка чтения входных регистров MB_ERR_R_HOLD_REGS = MB_R_HOLD_REGS + ERR_VALUES_START, ///< Ошибка чтения входных регистров
// error writting // error writting
MB_ERR_W_COIL = MB_W_COIL + ERR_VALUES_START, ///< Ошибка записи битовой ячейки MB_ERR_W_COIL = MB_W_COIL + ERR_VALUES_START, ///< Ошибка записи битовой ячейки
MB_ERR_W_HOLD_REG = MB_W_HOLD_REG + ERR_VALUES_START, ///< Ошибка записи одиночного регистра MB_ERR_W_HOLD_REG = MB_W_HOLD_REG + ERR_VALUES_START, ///< Ошибка записи одиночного регистра
MB_ERR_W_COILS = MB_W_COILS + ERR_VALUES_START, ///< Ошибка записи нескольких битовых ячеек MB_ERR_W_COILS = MB_W_COILS + ERR_VALUES_START, ///< Ошибка записи нескольких битовых ячеек
MB_ERR_W_HOLD_REGS = MB_W_HOLD_REGS + ERR_VALUES_START, ///< Ошибка записи нескольких регистров MB_ERR_W_HOLD_REGS = MB_W_HOLD_REGS + ERR_VALUES_START, ///< Ошибка записи нескольких регистров
}MB_FunctonTypeDef; }MB_FunctonTypeDef;
/** @brief Structure for MEI func codes */ /** @brief Structure for MEI func codes */
@ -123,7 +117,7 @@ typedef enum //MB_FunctonTypeDef
/** @brief Structure for decive identification message type */ /** @brief Structure for decive identification message type */
typedef struct typedef struct
{ {
MB_MEITypeDef MEI_Type; ///< MEI Type assigned number for Device Identification Interface MB_MEITypeDef MEI_Type; ///< MEI Type assigned number for Device Identification Interface
MB_ConformityTypeDef ReadDevId; MB_ConformityTypeDef ReadDevId;
MB_ConformityTypeDef Conformity; MB_ConformityTypeDef Conformity;
uint8_t MoreFollows; ///< in this library always a zero uint8_t MoreFollows; ///< in this library always a zero
@ -132,19 +126,19 @@ typedef struct
}MB_DevIdMsgTypeDef; }MB_DevIdMsgTypeDef;
/** @brief Structure for modbus messsage */ /** @brief Structure for modbus messsage */
typedef struct // RS_MsgTypeDef typedef struct // RS_MsgTypeDef
{ {
uint8_t MbAddr; ///< Modbus Slave Address uint8_t MbAddr; ///< Modbus Slave Address
MB_FunctonTypeDef Func_Code; ///< Modbus Function Code MB_FunctonTypeDef Func_Code; ///< Modbus Function Code
MB_DevIdMsgTypeDef DevId; ///< Read Device Identification Header struct MB_DevIdMsgTypeDef DevId; ///< Read Device Identification Header struct
uint16_t Addr; ///< Modbus Address of data uint16_t Addr; ///< Modbus Address of data
uint16_t Qnt; ///< Quantity of modbus data uint16_t Qnt; ///< Quantity of modbus data
uint8_t ByteCnt; ///< Quantity of bytes of data in message to transmit/receive uint8_t ByteCnt; ///< Quantity of bytes of data in message to transmit/receive
uint16_t DATA[DATA_SIZE]; ///< Modbus Data uint16_t DWDATA[DATA_SIZE]; ///< Modbus Data (Words)
MB_ExceptionTypeDef Except_Code; ///< Exception Code for the command MB_ExceptionTypeDef Except_Code; ///< Exception Code for the command
uint16_t MB_CRC; ///< Modbus CRC uint16_t MB_CRC; ///< Modbus CRC
}RS_MsgTypeDef; }RS_MsgTypeDef;
//-------------------------------------------------- //--------------------------------------------------
extern RS_MsgTypeDef MODBUS_MSG; extern RS_MsgTypeDef MODBUS_MSG;
@ -158,129 +152,129 @@ extern RS_MsgTypeDef MODBUS_MSG;
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
////////////////////---MODBUS MESSAGE DEFINES---///////////////////// ////////////////////---MODBUS MESSAGE DEFINES---/////////////////////
/** /**
* @addtogroup MODBUS_MESSAGE_DEFINES * @addtogroup MODBUS_MESSAGE_DEFINES
* @ingroup MODBUS * @ingroup MODBUS
* @brief Some defines for modbus * @brief Some defines for modbus
@{ @{
*/ */
/** @brief Structure for coils operation */ /** @brief Structure for coils operation */
typedef enum typedef enum
{ {
SET_COIL, SET_COIL,
RESET_COIL, RESET_COIL,
TOOGLE_COIL, TOOGLE_COIL,
}MB_CoilsOpTypeDef; }MB_CoilsOpTypeDef;
//-------------------------------------------------- //--------------------------------------------------
/** /**
* @brief Macros to set pointer to 16-bit array * @brief Macros to set pointer to 16-bit array
* @param _arr_ - массив регистров (16-бит). * @param _arr_ - массив регистров (16-бит).
*/ */
#define MB_Set_Arr16_Ptr(_arr_) ((uint16_t*)(&(_arr_))) #define MB_Set_Arr16_Ptr(_arr_) ((uint16_t*)(&(_arr_)))
/** /**
* @brief Macros to set pointer to register * @brief Macros to set pointer to register
* @param _parr_ - массив регистров. * @param _parr_ - массив регистров.
* @param _addr_ - Номер регистра (его индекс) от начала массива _arr_. * @param _addr_ - Номер регистра (его индекс) от начала массива _arr_.
*/ */
#define MB_Set_Register_Ptr(_parr_, _addr_) ((uint16_t *)(_parr_)+(_addr_)) #define MB_Set_Register_Ptr(_parr_, _addr_) ((uint16_t *)(_parr_)+(_addr_))
/** /**
* @brief Macros to set pointer to a certain register that contains certain coil * @brief Macros to set pointer to a certain register that contains certain coil
* @param _parr_ - массив коилов. * @param _parr_ - массив коилов.
* @param _coil_ - Номер коила от начала массива _arr_. * @param _coil_ - Номер коила от начала массива _arr_.
* @note Используется вместе с @ref MB_Set_Coil_Mask * @note Используется вместе с @ref MB_Set_Coil_Mask
@verbatim Пояснение выражений @verbatim Пояснение выражений
(_coil_/16) - get index (address shift) of register that contain certain coil (_coil_/16) - get index (address shift) of register that contain certain coil
Visual explanation: 30th coil in coils registers array Visual explanation: 30th coil in coils registers array
xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxCx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxCx
|register[0]----| |register[1]----| |register[0]----| |register[1]----|
|skip this------| |get this-------| |skip this------| |get this-------|
|shift to 14 bit| |shift to 14 bit|
@endverbatim @endverbatim
*/ */
#define MB_Set_Coil_Reg_Ptr(_parr_, _coil_) ((uint16_t *)(_parr_)+((_coil_)/16)) #define MB_Set_Coil_Reg_Ptr(_parr_, _coil_) ((uint16_t *)(_parr_)+((_coil_)/16))
/** /**
* @brief Macros to set mask to a certain bit in coils register * @brief Macros to set mask to a certain bit in coils register
* @param _coil_ - Номер коила от начала массива _arr_. * @param _coil_ - Номер коила от начала массива _arr_.
* @note Используется вместе с @ref MB_Set_Coil_Reg_Ptr * @note Используется вместе с @ref MB_Set_Coil_Reg_Ptr
@verbatim Пояснение выражений @verbatim Пояснение выражений
(16*(_coil_/16) - how many coils we need to skip. e.g. (16*30/16) - skip 16 coils from first register (16*(_coil_/16) - how many coils we need to skip. e.g. (16*30/16) - skip 16 coils from first register
_coil_-(16*(_coil_/16)) - shift to certain coil in certain register _coil_-(16*(_coil_/16)) - shift to certain coil in certain register
e.g. Coil(30) gets in register[1] (30/16 = 1) coil 14 (30 - (16*30/16) = 30 - 16 = 14) e.g. Coil(30) gets in register[1] (30/16 = 1) coil 14 (30 - (16*30/16) = 30 - 16 = 14)
Visual explanation: 30th coil in coils registers array Visual explanation: 30th coil in coils registers array
xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxCx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxCx
|register[0]----| |register[1]----| |register[0]----| |register[1]----|
|skip this------| |get this-------| |skip this------| |get this-------|
|shift to 14 bit| |shift to 14 bit|
@endverbatim @endverbatim
*/ */
#define MB_Set_Coil_Mask(_coil_) (1 << ( _coil_ - (16*((_coil_)/16)) )) #define MB_Set_Coil_Mask(_coil_) (1 << ( _coil_ - (16*((_coil_)/16)) ))
/** /**
* @brief Read Coil at its local address. * @brief Read Coil at its local address.
* @param _parr_ - массив коилов. * @param _parr_ - массив коилов.
* @param _coil_ - Номер коила от начала массива _arr_. * @param _coil_ - Номер коила от начала массива _arr_.
* @return uint16_t - Возвращает запрошенный коил на 0м бите. * @return uint16_t - Возвращает запрошенный коил на 0м бите.
* *
* @details Позволяет обратиться к коилу по адресу относительно _arr_. * @details Позволяет обратиться к коилу по адресу относительно _arr_.
*/ */
#define MB_Read_Coil_Local(_parr_, _coil_) (( *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) & MB_Set_Coil_Mask(_coil_) ) >> (_coil_)) #define MB_Read_Coil_Local(_parr_, _coil_) (( *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) & MB_Set_Coil_Mask(_coil_) ) >> (_coil_))
/** /**
* @brief Set Coil at its local address. * @brief Set Coil at its local address.
* @param _parr_ - указатель на массив коилов. * @param _parr_ - указатель на массив коилов.
* @param _coil_ - Номер коила от начала массива _arr_. * @param _coil_ - Номер коила от начала массива _arr_.
* *
* @details Позволяет обратиться к коилу по адресу относительно _arr_. * @details Позволяет обратиться к коилу по адресу относительно _arr_.
*/ */
#define MB_Set_Coil_Local(_parr_, _coil_) *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) |= MB_Set_Coil_Mask(_coil_) #define MB_Set_Coil_Local(_parr_, _coil_) *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) |= MB_Set_Coil_Mask(_coil_)
/** /**
* @brief Reset Coil at its local address. * @brief Reset Coil at its local address.
* @param _parr_ - указатель на массив коилов. * @param _parr_ - указатель на массив коилов.
* @param _coil_ - Номер коила от начала массива _arr_. * @param _coil_ - Номер коила от начала массива _arr_.
* *
* @details Позволяет обратиться к коилу по адресу относительно _arr_. * @details Позволяет обратиться к коилу по адресу относительно _arr_.
*/ */
#define MB_Reset_Coil_Local(_parr_, _coil_) *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) &= ~(MB_Set_Coil_Mask(_coil_)) #define MB_Reset_Coil_Local(_parr_, _coil_) *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) &= ~(MB_Set_Coil_Mask(_coil_))
/** /**
* @brief Set Coil at its local address. * @brief Set Coil at its local address.
* @param _parr_ - указатель на массив коилов. * @param _parr_ - указатель на массив коилов.
* @param _coil_ - Номер коила от начала массива _arr_. * @param _coil_ - Номер коила от начала массива _arr_.
* *
* @details Позволяет обратиться к коилу по адресу относительно _arr_. * @details Позволяет обратиться к коилу по адресу относительно _arr_.
*/ */
#define MB_Toogle_Coil_Local(_parr_, _coil_) *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) ^= MB_Set_Coil_Mask(_coil_) #define MB_Toogle_Coil_Local(_parr_, _coil_) *MB_Set_Coil_Reg_Ptr(_parr_, _coil_) ^= MB_Set_Coil_Mask(_coil_)
//-------------------------------------------------- //--------------------------------------------------
//------------------OTHER DEFINES------------------- //------------------OTHER DEFINES-------------------
#define RegisterType_Holding 0 #define RegisterType_Holding 0
#define RegisterType_Input 1 #define RegisterType_Input 1
#define RegisterType_Discrete 2 #define RegisterType_Discrete 2
// create hadnles and settings for uart, tim, rs with _modbus_ name // create hadnles and settings for uart, tim, rs with _modbus_ name
//-------------------------------------------------- //--------------------------------------------------
#ifndef Divide_Up #ifndef Divide_Up
/** /**
* @brief Calc dividing including remainder * @brief Calc dividing including remainder
* @param _val_ - делимое. * @param _val_ - делимое.
* @param _div_ - делитель. * @param _div_ - делитель.
* @details Если результат деления без остатка: он возвращается как есть * @details Если результат деления без остатка: он возвращается как есть
Если с остатком - округляется вверх Если с остатком - округляется вверх
*/ */
//#define Divide_Up(_val_, _div_) (((_val_)%(_div_))? (_val_)/(_div_)+1 : (_val_)/_div_) /* через тернарный оператор */ //#define Divide_Up(_val_, _div_) (((_val_)%(_div_))? (_val_)/(_div_)+1 : (_val_)/_div_) /* через тернарный оператор */
#define Divide_Up(_val_, _div_) ((_val_ - 1) / _div_) + 1 /* через мат выражение */ #define Divide_Up(_val_, _div_) ((_val_ - 1) / _div_) + 1 /* через мат выражение */
#endif #endif
#ifndef ByteSwap16 #ifndef ByteSwap16
/** /**
* @brief Swap between Little Endian and Big Endian * @brief Swap between Little Endian and Big Endian
* @param v - Переменная для свапа. * @param v - Переменная для свапа.
* @return v (new) - Свапнутая переменная. * @return v (new) - Свапнутая переменная.
* @details Переключения между двумя типами хранения слова: HI-LO байты и LO-HI байты. * @details Переключения между двумя типами хранения слова: HI-LO байты и LO-HI байты.
*/ */
#define ByteSwap16(v) (((v&0xFF00) >> (8)) | ((v&0x00FF) << (8))) #define ByteSwap16(v) (((v&0xFF00) >> (8)) | ((v&0x00FF) << (8)))
#endif #endif
/** GENERAL_MODBUS_STUFF /** GENERAL_MODBUS_STUFF
* @} * @}
@ -292,18 +286,18 @@ typedef enum
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
/////////////////////////---FUNCTIONS---///////////////////////////// /////////////////////////---FUNCTIONS---/////////////////////////////
/** /**
* @addtogroup MODBUS_FUNCTIONS * @addtogroup MODBUS_FUNCTIONS
* @ingroup MODBUS * @ingroup MODBUS
* @brief Function for controling modbus communication * @brief Function for controling modbus communication
*/ */
//----------------FUNCTIONS FOR USER---------------- //----------------FUNCTIONS FOR USER----------------
/** /**
* @addtogroup MODBUS_DATA_ACCESS_FUNCTIONS * @addtogroup MODBUS_DATA_ACCESS_FUNCTIONS
* @ingroup MODBUS_FUNCTIONS * @ingroup MODBUS_FUNCTIONS
* @brief Function for user use * @brief Function for user use
@{ @{
*/ */
/* First set up of MODBUS */ /* First set up of MODBUS */
void MODBUS_FirstInit(void); void MODBUS_FirstInit(void);
/* Set or Reset Coil at its global address */ /* Set or Reset Coil at its global address */
@ -314,14 +308,14 @@ uint16_t MB_Read_Coil_Global(uint16_t Addr, MB_ExceptionTypeDef *Exception);
/** MODBUS_DATA_ACCESS_FUNCTIONS /** MODBUS_DATA_ACCESS_FUNCTIONS
* @} * @}
*/ */
//---------PROCESS MODBUS COMMAND FUNCTIONS--------- //---------PROCESS MODBUS COMMAND FUNCTIONS---------
/** /**
* @addtogroup MODBUS_CMD_PROCESS_FUNCTIONS * @addtogroup MODBUS_CMD_PROCESS_FUNCTIONS
* @ingroup MODBUS_FUNCTIONS * @ingroup MODBUS_FUNCTIONS
* @brief Function process commands * @brief Function process commands
@{ @{
*/ */
/* Check is address valid for certain array */ /* Check is address valid for certain array */
MB_ExceptionTypeDef MB_Check_Address_For_Arr(uint16_t Addr, uint16_t Qnt, uint16_t R_ARR_ADDR, uint16_t R_ARR_NUMB); MB_ExceptionTypeDef MB_Check_Address_For_Arr(uint16_t Addr, uint16_t Qnt, uint16_t R_ARR_ADDR, uint16_t R_ARR_NUMB);
/* Define Address Origin for Input/Holding Registers */ /* Define Address Origin for Input/Holding Registers */
@ -334,7 +328,7 @@ uint8_t MB_Read_Coils(RS_MsgTypeDef *modbus_msg);
uint8_t MB_Read_Hold_Regs(RS_MsgTypeDef *modbus_msg); uint8_t MB_Read_Hold_Regs(RS_MsgTypeDef *modbus_msg);
/* Proccess command Read Input Registers (04 - 0x04) */ /* Proccess command Read Input Registers (04 - 0x04) */
uint8_t MB_Read_Input_Regs(RS_MsgTypeDef *modbus_msg); uint8_t MB_Read_Input_Regs(RS_MsgTypeDef *modbus_msg);
/* Proccess command Write Single Coils (05 - 0x05) */ /* Proccess command Write Single Coils (05 - 0x05) */
uint8_t MB_Write_Single_Coil(RS_MsgTypeDef *modbus_msg); uint8_t MB_Write_Single_Coil(RS_MsgTypeDef *modbus_msg);
/* Proccess command Write Multiple Coils (15 - 0x0F) */ /* Proccess command Write Multiple Coils (15 - 0x0F) */
uint8_t MB_Write_Miltuple_Coils(RS_MsgTypeDef *modbus_msg); uint8_t MB_Write_Miltuple_Coils(RS_MsgTypeDef *modbus_msg);
@ -345,9 +339,9 @@ uint8_t MB_Write_Miltuple_Regs(RS_MsgTypeDef *modbus_msg);
* @} * @}
*/ */
/////////////////////////---FUNCTIONS---///////////////////////////// /////////////////////////---FUNCTIONS---/////////////////////////////
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
/////////////////////////---CALC DEFINES---////////////////////////// /////////////////////////---CALC DEFINES---//////////////////////////
@ -356,7 +350,7 @@ uint8_t MB_Write_Miltuple_Regs(RS_MsgTypeDef *modbus_msg);
#ifndef Trace_MB_UART_Enter #ifndef Trace_MB_UART_Enter
#define Trace_MB_UART_Enter() #define Trace_MB_UART_Enter()
#endif //Trace_MB_UART_Enter #endif //Trace_MB_UART_Enter
#ifndef Trace_MB_UART_Exit #ifndef Trace_MB_UART_Exit
#define Trace_MB_UART_Exit() #define Trace_MB_UART_Exit()
#endif //Trace_MB_UART_Exit #endif //Trace_MB_UART_Exit
@ -364,7 +358,7 @@ uint8_t MB_Write_Miltuple_Regs(RS_MsgTypeDef *modbus_msg);
#ifndef Trace_MB_TIM_Enter #ifndef Trace_MB_TIM_Enter
#define Trace_MB_TIM_Enter() #define Trace_MB_TIM_Enter()
#endif //Trace_MB_TIM_Enter #endif //Trace_MB_TIM_Enter
#ifndef Trace_MB_TIM_Exit #ifndef Trace_MB_TIM_Exit
#define Trace_MB_TIM_Exit() #define Trace_MB_TIM_Exit()
#endif //Trace_MB_TIM_Exit #endif //Trace_MB_TIM_Exit

View File

@ -7,14 +7,25 @@
#ifndef _MODBUS_CONFIG_H_ #ifndef _MODBUS_CONFIG_H_
#define _MODBUS_CONFIG_H_ #define _MODBUS_CONFIG_H_
#define RS_IN_RTOS 20 ///< значение - период таска
// Включить/выключить debug // Включить/выключить debug
#define RS_DEBUG 0 ///< Отладка приема/передачи UART #define RS_DEBUG 1 ///< Отладка приема/передачи UART
#define MODBUS_DEBUG 0 ///< Отладка обработки запросов Modbus #define MODBUS_DEBUG 1 ///< Отладка обработки запросов Modbus
#define MODBUS_ERR_DEBUG 1 ///< Отладка ошибок по CAN #define MODBUS_ERR_DEBUG 1 ///< Отладка ошибок по CAN
// MODBUS PARAMS // MODBUS PARAMS
#define MODBUS_DEVICE_ID 1 ///< девайс текущего устройства #define MODBUS_DEVICE_ID 1 ///< девайс текущего устройства
#define MODBUS_TIMEOUT 5000 ///< максимальнйы тайтаут MB в тиках таймера #define MODBUS_TIMEOUT 5000 ///< максимальнйы тайтаут MB в мс
// PERIPH FUNCTIONS AND HANDLERS
#define HUART_TypeDef HardwareSerial
#define rs_huart Serial2 //используемый uart1`
#define MODBUS_SPEED 115200
#define MODBUS_RX_PIN 8
#define MODBUS_TX_PIN 9
// STRING OBJECTS MODBUS // STRING OBJECTS MODBUS
#define MODBUS_VENDOR_NAME "NIO PRIBOR" #define MODBUS_VENDOR_NAME "NIO PRIBOR"
@ -25,9 +36,6 @@
#define MODBUS_MODEL_NAME "Arduino" #define MODBUS_MODEL_NAME "Arduino"
#define MODBUS_USER_APPLICATION_NAME "" #define MODBUS_USER_APPLICATION_NAME ""
// PERIPH FUNCTIONS AND HANDLERS
#define rs_huart Serial1 //используемый uart
#define HUART_TypeDef HardwareSerial
/** /**
* @brief Поменять комманды 0x03 и 0x04 местами (для LabView терминалки от двигателей) * @brief Поменять комманды 0x03 и 0x04 местами (для LabView терминалки от двигателей)

View File

@ -29,10 +29,10 @@
При добавлении новых массивов регистров, необходимо их добавить в функцию MB_DefineRegistersAddress При добавлении новых массивов регистров, необходимо их добавить в функцию MB_DefineRegistersAddress
if(MB_Check_Address_For_Arr(Addr, Qnt, R_<NEW_ARRAY>_ADDR, R_<NEW_ARRAY>_QNT) == NO_ERRORS) if(MB_Check_Address_For_Arr(Addr, Qnt, R_<NEW_ARRAY>_ADDR, R_<NEW_ARRAY>_QNT) == NO_ERRORS)
{ {
*pRegs = MB_Set_Register_Ptr(&<NEW_ARRAY>, Addr); // начало регистров хранения/входных *pRegs = MB_Set_Register_Ptr(&<NEW_ARRAY>, Addr); // начало регистров хранения/входных
} }
@endverbatim @endverbatim
* @{ * @{
*/ */
@ -134,8 +134,8 @@ extern MB_DataStructureTypeDef MB_DATA;
*/ */
typedef struct typedef struct
{ {
unsigned length; unsigned length;
char *name; const char *name;
}MB_DeviceObjectTypeDef; }MB_DeviceObjectTypeDef;
/** /**
* @brief Структура для объектов Modbus * @brief Структура для объектов Modbus

View File

@ -1,70 +1,92 @@
/** /**
************************************************************************** **************************************************************************
* @file rs_message.cpp * @file rs_message.cpp
* @brief Модуль для реализации протоколов по RS/UART (Arduino). * @brief Модуль для работы с протоколами RS/UART на Arduino.
**************************************************************************\ **************************************************************************
* @details * @details
* Данный модуль реализует основные функции для приема и передачи сообщений * Данный модуль обеспечивает приём и передачу сообщений по протоколу RS
* по протоколу RS через UART. Реализована обработка приёма и передачи данных, * через UART на платформах Arduino. Поддерживаются два режима работы:
* управление состояниями RS, а также функции для инициализации и управления * - обычный (Arduino loop);
* периферией Arduino Serial. * - FreeRTOS (через StreamBuffer и отдельную задачу RS_Task).
* *
* Реализованы следующие функции: * Основные возможности:
* - RS_Init() инициализация структуры RS и привязка к Serial-порту. * - Инициализация и управление структурой RS_HandleTypeDef.
* - RS_Abort() остановка работы RS/UART с очисткой флагов и структур. * - Обработка приёма байтов, сборка пакетов и определение их длины.
* - RS_Handle_Transmit_Start() запуск передачи данных. * - Разбор полученных сообщений и формирование ответов.
* - RS_Process() обработка входящих данных (вызов в loop()). * - Управление состояниями приёма и передачи (флаги RX/TX, busy/free).
* - Таймаут приёма и аварийная остановка передачи/приёма.
* *
* В модуле также определён буфер RS_Buffer[] для хранения принимаемых/передаваемых данных. * Предоставляемые функции:
* - RS_Init() инициализация структуры RS и Serial порта.
* - RS_Abort() остановка работы RS/UART, очистка флагов.
* - RS_Handle_Transmit_Start() подготовка и отправка сообщения.
* - RS_Process() основной цикл обработки (Arduino loop).
* - RS_Process_Byte() обработка одного принятого байта (для FreeRTOS).
* - RS_UART_RX_Handler() ISR-приём данных UART (FreeRTOS).
* - RS_Task() FreeRTOS задача обработки UART.
* *
* Пользователь должен определить функции: * Пользователь должен реализовать слабые функции:
* - RS_Response() формирование ответа на принятое сообщение. * - RS_Response() формирование ответа на сообщение.
* - RS_Collect_Message() подготовка сообщения для передачи. * - RS_Collect_Message() заполнение буфера перед передачей.
* - RS_Parse_Message() разбор принятого сообщения. * - RS_Parse_Message() разбор принятого пакета.
* - RS_Define_Size_of_RX_Message() определение размера входящих данных. * - RS_Define_Size_of_RX_Message() определение длины ожидаемого пакета.
* *
* Буфер для приёма/передачи: RS_Buffer[MSG_SIZE_MAX].
*
* @note * @note
* Для корректной работы требуется вызывать RS_Process() в основном цикле программы. * - В режиме Arduino loop необходимо вызывать RS_Process() в основном цикле.
* UART используется через стандартный Arduino Stream API (write(), read(), available()). * - В режиме FreeRTOS требуется определить макрос RS_IN_RTOS,
* создать задачу RS_Task и подключить RS_UART_RX_Handler() к ISR UART.
* - UART используется через стандартный Arduino Stream API (write, read, available).
* *
@verbatim * Пример использования (Arduino loop):
//-------------------Функции-------------------// * @verbatim
Functions: users RS_HandleTypeDef hRS;
- RS_Parse_Message Разбор принятого сообщения RS_MsgTypeDef msg;
- RS_Collect_Message Заполнение структуры сообщения и буфера hRS.pMessagePtr = &msg;
- RS_Response Ответ на сообщение RS_Init(&hRS, &Serial, 115200, NULL);
- RS_Define_Size_of_RX_Message Определение размера принимаемых данных
void loop() {
RS_Process(&hRS);
}
* @endverbatim
* Пример использования с RTOS:
* @verbatim
RS_HandleTypeDef hRS;
RS_MsgTypeDef msg;
hRS.pMessagePtr = &msg;
RS_Init(&hRS, &Serial, 115200, NULL);
Functions: general xTaskCreate(RS_Task, "RS_Task", 256, &hRS, 1, NULL);
- RS_Init Инициализация структуры RS и привязка Serial //...
- RS_Abort Остановка приёма/передачи void eventSerial() {
- RS_Handle_Transmit_Start Запуск передачи сообщения RS_UART_RX_Handler(&hmodbus1);
- RS_Process Обработка приёма сообщений (в loop) }
* @endverbatim
**************************************************************************/
@endverbatim #include "modbus/rs_message.h"
*************************************************************************/
#include "rs_message.h"
uint8_t RS_Buffer[MSG_SIZE_MAX]; // uart buffer uint8_t RS_Buffer[MSG_SIZE_MAX]; // uart buffer
//------------------------------------------------------------------- //-------------------------------------------------------------------
//-------------------------GENERAL FUNCTIONS------------------------- //-------------------------GENERAL FUNCTIONS-------------------------
/** /**
* @brief Initialize UART and handle RS stucture. * @brief Initialize UART and handle RS stucture.
* @param hRS - указатель на хендлер RS. * @param hRS - указатель на хендлер RS.
* @param SerialPort - указатель на структуру с настройками UART. * @param SerialPort - указатель на структуру с настройками UART.
* @param pRS_BufferPtr - указатель на буффер для приема-передачи по UART. Если он NULL, то поставиться библиотечный буфер. * @param pRS_BufferPtr - указатель на буффер для приема-передачи по UART. Если он NULL, то поставиться библиотечный буфер.
* @return RS_RES - статус о состоянии RS после инициализации. * @return RS_RES - статус о состоянии RS после инициализации.
* @note Инициализация перефирии и структуры для приема-передачи по RS. * @note Инициализация периферии и структуры для приема-передачи по RS.
*/ */
RS_StatusTypeDef RS_Init(RS_HandleTypeDef *hRS, HUART_TypeDef *SerialPort, uint8_t *pRS_BufferPtr) { RS_StatusTypeDef RS_Init(RS_HandleTypeDef *hRS, HUART_TypeDef *SerialPort, uint32_t baudRate, uint8_t *pRS_BufferPtr) {
if (!hRS || !SerialPort) { if (!hRS || !SerialPort) {
RS_DEBUG_PRINT("[RS] Init error: null handler or port"); RS_DEBUG_PRINT("[RS] Init error: null handler or port");
return RS_ERR; return RS_ERR;
} }
hRS->huart = SerialPort; hRS->huart = SerialPort;
hRS->baudRate = baudRate;
hRS->pBufferPtr = pRS_BufferPtr ? pRS_BufferPtr : RS_Buffer; hRS->pBufferPtr = pRS_BufferPtr ? pRS_BufferPtr : RS_Buffer;
hRS->RS_STATUS = RS_OK; hRS->RS_STATUS = RS_OK;
RS_Set_Free(hRS); RS_Set_Free(hRS);
@ -74,24 +96,26 @@ RS_StatusTypeDef RS_Init(RS_HandleTypeDef *hRS, HUART_TypeDef *SerialPort, uint8
hRS->f.RX_Half = 0; hRS->f.RX_Half = 0;
hRS->lastByteTime = 0; hRS->lastByteTime = 0;
RS_EnableReceive(); RS_EnableReceive();
RS_Set_Busy(hRS); RS_Set_Busy(hRS);
RS_Set_RX_Flags(hRS); RS_Set_RX_Flags(hRS);
hRS->huart->begin(hRS->baudRate, SERIAL_8N1, hRS->rx_pin, hRS->tx_pin);
RS_DEBUG_PRINT("[RS] Initialized successfully"); RS_DEBUG_PRINT("[RS] Initialized successfully");
return RS_OK; return RS_OK;
} }
/** /**
* @brief Abort RS/UART. * @brief Abort RS/UART.
* @param hRS - указатель на хендлер RS. * @param hRS - указатель на хендлер RS.
* @param AbortMode - выбор, что надо отменить. * @param AbortMode - выбор, что надо отменить.
- ABORT_TX: Отмена передачи по ЮАРТ, с очищением флагов TX, - ABORT_TX: Отмена передачи по ЮАРТ, с очищением флагов TX,
- ABORT_RX: Отмена приема по ЮАРТ, с очищением флагов RX, - ABORT_RX: Отмена приема по ЮАРТ, с очищением флагов RX,
- ABORT_RX_TX: Отмена приема и передачи по ЮАРТ, - ABORT_RX_TX: Отмена приема и передачи по ЮАРТ,
- ABORT_RS: Отмена приема-передачи RS, с очищением всей структуры. - ABORT_RS: Отмена приема-передачи RS, с очищением всей структуры.
* @return RS_RES - статус о состоянии RS после аборта. * @return RS_RES - статус о состоянии RS после аборта.
* @note В Arduino аппаратный UART (Serial) не отключается физически, * @details В Arduino аппаратный UART (Serial) не отключается физически,
* т.к. стандартный API HardwareSerial не даёт прямого доступа * т.к. стандартный API HardwareSerial не даёт прямого доступа
* к регистрах UART. RS_Abort лишь очищает внутренние флаги * к регистрах UART. RS_Abort лишь очищает внутренние флаги
* и структуры, имитируя "отключение". * и структуры, имитируя "отключение".
@ -121,12 +145,12 @@ RS_StatusTypeDef RS_Abort(RS_HandleTypeDef *hRS, RS_AbortTypeDef AbortMode) {
} }
/** /**
* @brief Handle for starting transmit. * @brief Handle for starting transmit.
* @param hRS - указатель на хендлер RS. * @param hRS - указатель на хендлер RS.
* @param RS_msg - указатель на структуру сообщения. * @param RS_msg - указатель на структуру сообщения.
* @return RS_RES - статус о состоянии RS после инициализации передачи. * @return RS_RES - статус о состоянии RS после инициализации передачи.
* @note Определяет отвечать ли на команду или нет. * @details Определяет отвечать ли на команду или нет.
*/ */
RS_StatusTypeDef RS_Handle_Transmit_Start(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg) RS_StatusTypeDef RS_Handle_Transmit_Start(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg)
{ {
if (hRS == nullptr || RS_msg == nullptr) { if (hRS == nullptr || RS_msg == nullptr) {
@ -152,25 +176,38 @@ RS_StatusTypeDef RS_Handle_Transmit_Start(RS_HandleTypeDef *hRS, RS_MsgTypeDef *
hRS->huart->write(hRS->pBufferPtr, hRS->RS_Message_Size); hRS->huart->write(hRS->pBufferPtr, hRS->RS_Message_Size);
RS_Set_TX_End(hRS); RS_Set_TX_End(hRS);
RS_Set_RX_Flags(hRS); RS_Set_RX_Flags(hRS);
RS_Set_RX_Flags(hRS); RS_Set_RX_Flags(hRS);
RS_DEBUG_PRINT("[RS] TX finished"); RS_DEBUG_PRINT("[RS] TX finished");
return RS_OK; return RS_OK;
} }
#ifdef RS_IN_RTOS
/** /**
* @brief Main RS processing function. * @brief Задача обработки UART приёма (FreeRTOS).
* @param pvParameters - указатель на RS_HandleTypeDef (передаётся при создании задачи).
* @details Вызывает функцию обработки приема UART по протоколу.
*/
void RS_Task(void *pvParameters) {
RS_HandleTypeDef *hRS = (RS_HandleTypeDef *)pvParameters;
uint8_t rxBuf[64];
for (;;) {
RS_Process(hRS);
vTaskDelay(pdMS_TO_TICKS(hRS->taskDelay));
}
}
#endif // RS_IN_RTOS
/**
* @brief Основная функция обработки RS (вариант без FreeRTOS).
* @param hRS - указатель на хендлер RS. * @param hRS - указатель на хендлер RS.
* @return None. * @note Используется в Arduino loop(), если проект без FreeRTOS.
* @note Функция должна вызываться в основном цикле (loop()). * @details Выполняет проверку таймаутов, обработку поступающих байт из UART
* Выполняет проверку таймаутов, обработку поступающих байт из UART * по протоколу
* и вызов пользовательских функций:
* - RS_Define_Size_of_RX_Message() для определения размера пакета;
* - RS_Parse_Message() для разбора принятого сообщения;
* - RS_Response() для ответа, если сообщение адресовано текущему устройству.
* В случае таймаута выполняется RS_Abort() с режимом ABORT_RX.
*/ */
void RS_Process(RS_HandleTypeDef *hRS) void RS_Process(RS_HandleTypeDef *hRS)
{ {
@ -215,7 +252,7 @@ void RS_Process(RS_HandleTypeDef *hRS)
// Если достигнут размер первой части пакета — определяем полный размер // Если достигнут размер первой части пакета — определяем полный размер
if (rx_index == RX_FIRST_PART_SIZE && (hRS->f.RX_Half == 0) && hRS->sRS_RX_Size_Mode == RS_RX_Size_NotConst) { if (rx_index == RX_FIRST_PART_SIZE && (hRS->f.RX_Half == 0) && hRS->sRS_RX_Size_Mode == RS_RX_Size_NotConst) {
hRS->f.RX_Half = 1; hRS->f.RX_Half = 1;
uint32_t data_size; uint32_t data_size;
RS_DEBUG_PRINT("[RS] Defining size..."); RS_DEBUG_PRINT("[RS] Defining size...");
RS_Define_Size_of_RX_Message(hRS, &data_size); RS_Define_Size_of_RX_Message(hRS, &data_size);
@ -251,39 +288,39 @@ void RS_Process(RS_HandleTypeDef *hRS)
//------------------------------------------------------------------- //-------------------------------------------------------------------
//--------------WEAK PROTOTYPES FOR PROCESSING MESSAGE--------------- //--------------WEAK PROTOTYPES FOR PROCESSING MESSAGE---------------
/** /**
* @brief Respond accord to received message. * @brief Respond accord to received message.
* @param hRS - указатель на хендлер RS. * @param hRS - указатель на хендлер RS.
* @param RS_msg - указатель на структуру сообщения. * @param RS_msg - указатель на структуру сообщения.
* @return RS_RES - статус о результате ответа на комманду. * @return RS_RES - статус о результате ответа на комманду.
* @note Обработка принятой комманды и ответ на неё. * @details Обработка принятой комманды и ответ на неё.
*/ */
__attribute__((weak)) RS_StatusTypeDef RS_Response(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg) { return RS_ERR; } __attribute__((weak)) RS_StatusTypeDef RS_Response(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg) { return RS_ERR; }
/** /**
* @brief Collect message in buffer to transmit it. * @brief Collect message in buffer to transmit it.
* @param hRS - указатель на хендлер RS. * @param hRS - указатель на хендлер RS.
* @param RS_msg - указатель на структуру сообщения. * @param RS_msg - указатель на структуру сообщения.
* @param msg_uart_buff - указатель на буффер UART. * @param msg_uart_buff - указатель на буффер UART.
* @return RS_RES - статус о результате заполнения буфера. * @return RS_RES - статус о результате заполнения буфера.
* @note Заполнение буффера UART из структуры сообщения. * @details Заполнение буффера UART из структуры сообщения.
*/ */
__attribute__((weak)) RS_StatusTypeDef RS_Collect_Message(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg, uint8_t *msg_uart_buff) { return RS_ERR; } __attribute__((weak)) RS_StatusTypeDef RS_Collect_Message(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg, uint8_t *msg_uart_buff) { return RS_ERR; }
/** /**
* @brief Parse message from buffer to process it. * @brief Parse message from buffer to process it.
* @param hRS - указатель на хендлер RS. * @param hRS - указатель на хендлер RS.
* @param RS_msg - указатель на структуру сообщения. * @param RS_msg - указатель на структуру сообщения.
* @param msg_uart_buff - указатель на буффер UART. * @param msg_uart_buff - указатель на буффер UART.
* @return RS_RES - статус о результате заполнения структуры. * @return RS_RES - статус о результате заполнения структуры.
* @note Заполнение структуры сообщения из буффера UART. * @details Заполнение структуры сообщения из буффера UART.
*/ */
__attribute__((weak)) RS_StatusTypeDef RS_Parse_Message(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg, uint8_t *msg_uart_buff) { return RS_ERR; } __attribute__((weak)) RS_StatusTypeDef RS_Parse_Message(RS_HandleTypeDef *hRS, RS_MsgTypeDef *RS_msg, uint8_t *msg_uart_buff) { return RS_ERR; }
/** /**
* @brief Define size of RX Message that need to be received. * @brief Define size of RX Message that need to be received.
* @param hRS - указатель на хендлер RS. * @param hRS - указатель на хендлер RS.
* @param rx_data_size - указатель на переменную для записи кол-ва байт для принятия. * @param rx_data_size - указатель на переменную для записи кол-ва байт для принятия.
* @return RS_RES - статус о корректности рассчета кол-ва байт для принятия. * @return RS_RES - статус о корректности рассчета кол-ва байт для принятия.
* @note Определение сколько байтов надо принять по протоколу. * @details Определение сколько байтов надо принять по протоколу.
*/ */
__attribute__((weak)) RS_StatusTypeDef RS_Define_Size_of_RX_Message(RS_HandleTypeDef *hRS, uint32_t *rx_data_size) { return RS_ERR; } __attribute__((weak)) RS_StatusTypeDef RS_Define_Size_of_RX_Message(RS_HandleTypeDef *hRS, uint32_t *rx_data_size) { return RS_ERR; }

View File

@ -4,7 +4,7 @@
* @brief Заголовочный файл для модуля реализации протоколов по RS/UART. * @brief Заголовочный файл для модуля реализации протоколов по RS/UART.
************************************************************************** **************************************************************************
* @defgroup RS_TOOLS * @defgroup RS_TOOLS
* @brief Всякое для работы по UART/RS * @brief Всякое для работы по UART/RS
************************************************************************** **************************************************************************
@details @details
************************************************************************** **************************************************************************
@ -12,7 +12,7 @@
- Определить структуру сообщения RS_MsgTypeDef и - Определить структуру сообщения RS_MsgTypeDef и
дефайны RX_FIRST_PART_SIZE и MSG_SIZE_MAX. дефайны RX_FIRST_PART_SIZE и MSG_SIZE_MAX.
- Подключить этот файл в раздел rs_message.h. - Подключить этот файл в раздел rs_message.h.
- Определить функции для обработки сообщения: RS_Parse_Message(), - Определить функции для обработки сообщения: RS_Parse_Message(),
RS_Collect_Message(), RS_Response(), RS_Define_Size_of_RX_Message() RS_Collect_Message(), RS_Response(), RS_Define_Size_of_RX_Message()
************************************************************************** **************************************************************************
@verbatim @verbatim
@ -21,7 +21,7 @@
*************************************************************************/ *************************************************************************/
#ifndef __RS_LIB_H_ #ifndef __RS_LIB_H_
#define __RS_LIB_H_ #define __RS_LIB_H_
#include "modbus.h" #include "modbus/modbus.h"
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
////////////////////////////---DEFINES---//////////////////////////// ////////////////////////////---DEFINES---////////////////////////////
@ -75,94 +75,99 @@
///////////////////////---STRUCTURES & ENUMS---////////////////////// ///////////////////////---STRUCTURES & ENUMS---//////////////////////
//------------------ENUMERATIONS-------------------- //------------------ENUMERATIONS--------------------
/** @brief Enums for respond CMD about RS status */ /** @brief Enums for respond CMD about RS status */
typedef enum // RS_StatusTypeDef typedef enum // RS_StatusTypeDef
{ {
/* IN-CODE STATUS (start from 0x01, and goes up)*/ /* IN-CODE STATUS (start from 0x01, and goes up)*/
/*0x01*/ RS_OK = 0x01, /*0x01*/ RS_OK = 0x01,
/*0x02*/ RS_ERR, /*0x02*/ RS_ERR,
/*0x03*/ RS_ABORTED, /*0x03*/ RS_ABORTED,
/*0x04*/ RS_BUSY, /*0x04*/ RS_BUSY,
/*0x05*/ RS_SKIP, /*0x05*/ RS_SKIP,
/*0x06*/ RS_COLLECT_MSG_ERR, /*0x06*/ RS_COLLECT_MSG_ERR,
/*0x07*/ RS_PARSE_MSG_ERR, /*0x07*/ RS_PARSE_MSG_ERR,
// reserved values // reserved values
// /*0x00*/ RS_UNKNOWN_ERR = 0x00, ///< reserved for case, if no one error founded (nothing changed response from zero) // /*0x00*/ RS_UNKNOWN_ERR = 0x00, ///< reserved for case, if no one error founded (nothing changed response from zero)
}RS_StatusTypeDef; }RS_StatusTypeDef;
/** @brief Enums for RS Modes */ /** @brief Enums for RS Modes */
typedef enum // RS_ModeTypeDef typedef enum // RS_ModeTypeDef
{ {
SLAVE_ALWAYS_WAIT = 0x01, ///< Slave mode with infinity waiting SLAVE_ALWAYS_WAIT = 0x01, ///< Slave mode with infinity waiting
SLAVE_TIMEOUT_WAIT = 0x02, ///< Slave mode with waiting with timeout SLAVE_TIMEOUT_WAIT = 0x02, ///< Slave mode with waiting with timeout
// MASTER = 0x03, ///< Master mode // MASTER = 0x03, ///< Master mode
}RS_ModeTypeDef; }RS_ModeTypeDef;
/** @brief Enums for Abort modes */ /** @brief Enums for Abort modes */
typedef enum // RS_AbortTypeDef typedef enum // RS_AbortTypeDef
{ {
ABORT_TX = 0x01, ///< Abort transmit ABORT_TX = 0x01, ///< Abort transmit
ABORT_RX = 0x02, ///< Abort receive ABORT_RX = 0x02, ///< Abort receive
ABORT_RX_TX = 0x03, ///< Abort receive and transmit ABORT_RX_TX = 0x03, ///< Abort receive and transmit
ABORT_RS = 0x04, ///< Abort uart and reset RS structure ABORT_RS = 0x04, ///< Abort uart and reset RS structure
}RS_AbortTypeDef; }RS_AbortTypeDef;
/** @brief Enums for RX Size modes */ /** @brief Enums for RX Size modes */
typedef enum // RS_RXSizeTypeDef typedef enum // RS_RXSizeTypeDef
{ {
RS_RX_Size_Const = 0x01, ///< size of receiving message is constant RS_RX_Size_Const = 0x01, ///< size of receiving message is constant
RS_RX_Size_NotConst = 0x02, ///< size of receiving message isnt constant RS_RX_Size_NotConst = 0x02, ///< size of receiving message isnt constant
} RS_RX_SizeTypeDef; } RS_RX_SizeTypeDef;
//-----------STRUCTURE FOR HANDLE RS------------ //-----------STRUCTURE FOR HANDLE RS------------
/** @brief Struct for flags RS */ /** @brief Struct for flags RS */
typedef struct typedef struct
{ {
unsigned RX_Half:1; ///< flag: 0 - receiving msg before ByteCnt, 0 - receiving msg after ByteCnt unsigned RX_Half:1; ///< flag: 0 - receiving msg before ByteCnt, 0 - receiving msg after ByteCnt
unsigned RS_Busy:1; ///< flag: 1 - RS is busy, 0 - RS isnt busy
unsigned RX_Ongoing:1; ///< flag: 1 - receiving data right now, 0 - waiting for receiving data
unsigned RX_Busy:1; ///< flag: 1 - receiving is active, 0 - receiving isnt active unsigned RS_Busy:1; ///< flag: 1 - RS is busy, 0 - RS isnt busy
unsigned TX_Busy:1; ///< flag: 1 - transmiting is active, 0 - transmiting isnt active unsigned RX_Ongoing:1; ///< flag: 1 - receiving data right now, 0 - waiting for receiving data
unsigned RX_Done:1; ///< flag: 1 - receiving is done, 0 - receiving isnt done unsigned RX_Busy:1; ///< flag: 1 - receiving is active, 0 - receiving isnt active
unsigned TX_Done:1; ///< flag: 1 - transmiting is done, 0 - transmiting isnt done unsigned TX_Busy:1; ///< flag: 1 - transmiting is active, 0 - transmiting isnt active
// setted by user unsigned RX_Done:1; ///< flag: 1 - receiving is done, 0 - receiving isnt done
unsigned MessageHandled:1; ///< flag: 1 - RS command is handled, 0 - RS command isnt handled yet unsigned TX_Done:1; ///< flag: 1 - transmiting is done, 0 - transmiting isnt done
unsigned EchoResponse:1; ///< flag: 1 - response with received msg, 0 - response with own msg
unsigned DeferredResponse:1; ///< flag: 1 - response not in interrupt, 0 - response in interrupt // setted by user
unsigned ReInit_UART:1; ///< flag: 1 - need to reinitialize uart, 0 - nothing unsigned MessageHandled:1; ///< flag: 1 - RS command is handled, 0 - RS command isnt handled yet
unsigned EchoResponse:1; ///< flag: 1 - response with received msg, 0 - response with own msg
unsigned DeferredResponse:1; ///< flag: 1 - response not in interrupt, 0 - response in interrupt
unsigned ReInit_UART:1; ///< flag: 1 - need to reinitialize uart, 0 - nothing
}RS_FlagsTypeDef; }RS_FlagsTypeDef;
/** /**
* @brief Handle for RS communication. * @brief Handle for RS communication.
* @note Prefixes: h - handle, s - settings, f - flag * @note Prefixes: h - handle, s - settings, f - flag
*/ */
typedef struct // RS_HandleTypeDef typedef struct // RS_HandleTypeDef
{ {
/* MESSAGE */ /* MESSAGE */
uint8_t ID; ///< ID of RS "channel" uint8_t ID; ///< ID of RS "channel"
RS_MsgTypeDef *pMessagePtr; ///< pointer to message struct RS_MsgTypeDef *pMessagePtr; ///< pointer to message struct
uint8_t *pBufferPtr; ///< pointer to message buffer uint8_t *pBufferPtr; ///< pointer to message buffer
uint32_t RS_Message_Size; ///< size of whole message, not only data #ifdef RS_IN_RTOS
uint16_t taskDelay; ///< freertos buffer
/* HANDLERS and SETTINGS */ #endif
HUART_TypeDef *huart; ///< handler for used uart uint32_t RS_Message_Size; ///< size of whole message, not only data
RS_ModeTypeDef sRS_Mode; ///< setting: slave or master @ref RS_ModeTypeDef
uint16_t sRS_Timeout; ///< setting: timeout in ms
RS_RX_SizeTypeDef sRS_RX_Size_Mode; ///< setting: 1 - not const, 0 - const
/* FLAGS */
RS_FlagsTypeDef f; ///< These flags for controling receive/transmit
/* RS STATUS */ /* HANDLERS and SETTINGS */
uint8_t tx_pin; ///< Transmit pin
uint8_t rx_pin; ///< Receive pin
HUART_TypeDef *huart; ///< handler for used uart
RS_ModeTypeDef sRS_Mode; ///< setting: slave or master @ref RS_ModeTypeDef
uint16_t sRS_Timeout; ///< setting: timeout in ms
RS_RX_SizeTypeDef sRS_RX_Size_Mode; ///< setting: 1 - not const, 0 - const
/* FLAGS */
RS_FlagsTypeDef f; ///< These flags for controling receive/transmit
/* RS STATUS */
unsigned long lastByteTime; unsigned long lastByteTime;
unsigned long baudRate; unsigned long baudRate;
RS_StatusTypeDef RS_STATUS; ///< RS status RS_StatusTypeDef RS_STATUS; ///< RS status
}RS_HandleTypeDef; }RS_HandleTypeDef;
extern RS_HandleTypeDef hmodbus1; extern RS_HandleTypeDef hmodbus1;
@ -187,9 +192,12 @@ RS_StatusTypeDef RS_Define_Size_of_RX_Message(RS_HandleTypeDef *hRS, uint32_t *r
//-------------------------GENERAL FUNCTIONS------------------------- //-------------------------GENERAL FUNCTIONS-------------------------
/*-----------------Should be called from main code-----------------*/ /*-----------------Should be called from main code-----------------*/
/* Задача обработки UART приёма (FreeRTOS) */
void RS_Task(void *pvParameters);
/* Основная функция обработки RS */
void RS_Process(RS_HandleTypeDef *hRS); void RS_Process(RS_HandleTypeDef *hRS);
/* Initialize UART and handle RS stucture */ /* Initialize UART and handle RS stucture */
RS_StatusTypeDef RS_Init(RS_HandleTypeDef *hRS, HUART_TypeDef *huart, uint8_t *pRS_BufferPtr); RS_StatusTypeDef RS_Init(RS_HandleTypeDef *hRS, HUART_TypeDef *SerialPort, uint32_t baudRate, uint8_t *pRS_BufferPtr);
/* Abort RS/UART */ /* Abort RS/UART */
RS_StatusTypeDef RS_Abort(RS_HandleTypeDef *hRS, RS_AbortTypeDef AbortMode); RS_StatusTypeDef RS_Abort(RS_HandleTypeDef *hRS, RS_AbortTypeDef AbortMode);
/* Handle for starting transmit */ /* Handle for starting transmit */