Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed
Fork of 2-ComfileHMI_Modbus by
SimpleModbus.cpp@4:217cca9f2592, 2016-09-12 (annotated)
- Committer:
- hyx2001
- Date:
- Mon Sep 12 09:31:11 2016 +0000
- Revision:
- 4:217cca9f2592
- Parent:
- 2:f0fc57045b3d
ComfileHMI_Modbus
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
hyx2001 | 2:f0fc57045b3d | 1 | #include "mbed.h" |
hyx2001 | 2:f0fc57045b3d | 2 | #include "SimpleModbus.h" |
hyx2001 | 2:f0fc57045b3d | 3 | |
hyx2001 | 2:f0fc57045b3d | 4 | static Ticker ticker; |
hyx2001 | 2:f0fc57045b3d | 5 | static comfileHMI HMI; |
hyx2001 | 2:f0fc57045b3d | 6 | |
hyx2001 | 2:f0fc57045b3d | 7 | void StartModbus(PinName tx, PinName rx, long baud,u8 addr ,u16 *Register, u8 *Coil ) |
hyx2001 | 2:f0fc57045b3d | 8 | { |
hyx2001 | 2:f0fc57045b3d | 9 | //comfileHMI HMI; |
hyx2001 | 2:f0fc57045b3d | 10 | static RawSerial Device(tx, rx); |
hyx2001 | 2:f0fc57045b3d | 11 | Device.baud(baud); |
hyx2001 | 2:f0fc57045b3d | 12 | Device.format(8, SerialBase::None, 1); |
hyx2001 | 2:f0fc57045b3d | 13 | HMI.init_comfileHMI(&Device, addr, Register, Coil); |
hyx2001 | 2:f0fc57045b3d | 14 | Device.attach(&HMI, &comfileHMI::Rx_interrupt, Serial::RxIrq); |
hyx2001 | 2:f0fc57045b3d | 15 | } |
hyx2001 | 2:f0fc57045b3d | 16 | |
hyx2001 | 2:f0fc57045b3d | 17 | void comfileHMI::init_comfileHMI(RawSerial* Serial, u8 addr, u16 *Register, u8 *Coil) |
hyx2001 | 2:f0fc57045b3d | 18 | { |
hyx2001 | 2:f0fc57045b3d | 19 | __modbusComCh=0; |
hyx2001 | 2:f0fc57045b3d | 20 | __modbusSlaveAdr=0; |
hyx2001 | 2:f0fc57045b3d | 21 | __modbusBroadMode = 0; |
hyx2001 | 2:f0fc57045b3d | 22 | __modbusFoundFrame = 0; |
hyx2001 | 2:f0fc57045b3d | 23 | __modbusIntervalCounter=0;; |
hyx2001 | 2:f0fc57045b3d | 24 | |
hyx2001 | 2:f0fc57045b3d | 25 | __modbusWordBuffer = NULL; |
hyx2001 | 2:f0fc57045b3d | 26 | __modbusBitBuffer = NULL; |
hyx2001 | 2:f0fc57045b3d | 27 | |
hyx2001 | 2:f0fc57045b3d | 28 | __save_pointer[0]=0; |
hyx2001 | 2:f0fc57045b3d | 29 | __save_pointer[1]=0; |
hyx2001 | 2:f0fc57045b3d | 30 | __save_pointer[2]=0; |
hyx2001 | 2:f0fc57045b3d | 31 | __save_pointer[3]=0; |
hyx2001 | 2:f0fc57045b3d | 32 | |
hyx2001 | 2:f0fc57045b3d | 33 | __action_pointer[0]=__ring_buffer_max; |
hyx2001 | 2:f0fc57045b3d | 34 | __action_pointer[1]=__ring_buffer_max; |
hyx2001 | 2:f0fc57045b3d | 35 | __action_pointer[2]=__ring_buffer_max; |
hyx2001 | 2:f0fc57045b3d | 36 | __action_pointer[3]=__ring_buffer_max; |
hyx2001 | 2:f0fc57045b3d | 37 | |
hyx2001 | 2:f0fc57045b3d | 38 | __modbusSwitch[0]=0; |
hyx2001 | 2:f0fc57045b3d | 39 | __modbusSwitch[1]=0; |
hyx2001 | 2:f0fc57045b3d | 40 | __modbusSwitch[2]=0; |
hyx2001 | 2:f0fc57045b3d | 41 | __modbusSwitch[3]=0; |
hyx2001 | 2:f0fc57045b3d | 42 | __modbusBlankCheck = 0; |
hyx2001 | 2:f0fc57045b3d | 43 | |
hyx2001 | 2:f0fc57045b3d | 44 | device = Serial; |
hyx2001 | 2:f0fc57045b3d | 45 | startSimpleModbus(0, addr, Register, Coil); |
hyx2001 | 4:217cca9f2592 | 46 | ticker.attach_us(this, &comfileHMI::RunTime_HMI, 500); |
hyx2001 | 2:f0fc57045b3d | 47 | } |
hyx2001 | 2:f0fc57045b3d | 48 | |
hyx2001 | 2:f0fc57045b3d | 49 | /******************************************************************************* |
hyx2001 | 2:f0fc57045b3d | 50 | * Function Name : SysTickHandler (1mS마다 걸린다.) |
hyx2001 | 2:f0fc57045b3d | 51 | *******************************************************************************/ |
hyx2001 | 2:f0fc57045b3d | 52 | // 이 숫자를 바꾸면, 모드버스 수신후 응답 간격이 바뀐다. 5=5mS, |
hyx2001 | 2:f0fc57045b3d | 53 | #define __modbusReturnInterval 5 |
hyx2001 | 2:f0fc57045b3d | 54 | // 1mS 마다 인터럽트가 걸리는 루틴 |
hyx2001 | 2:f0fc57045b3d | 55 | // 이곳에서 모드버스관련 처리를 한다. |
hyx2001 | 2:f0fc57045b3d | 56 | |
hyx2001 | 2:f0fc57045b3d | 57 | //Ticker timer_1; |
hyx2001 | 2:f0fc57045b3d | 58 | void comfileHMI::Rx_interrupt() |
hyx2001 | 2:f0fc57045b3d | 59 | { |
hyx2001 | 2:f0fc57045b3d | 60 | while (device->readable()){ push_ringbuffer( 0,device->getc() );} |
hyx2001 | 2:f0fc57045b3d | 61 | return; |
hyx2001 | 2:f0fc57045b3d | 62 | } |
hyx2001 | 2:f0fc57045b3d | 63 | |
hyx2001 | 2:f0fc57045b3d | 64 | void comfileHMI::RunTime_HMI() |
hyx2001 | 2:f0fc57045b3d | 65 | { |
hyx2001 | 2:f0fc57045b3d | 66 | // MODBUS관련 처리 |
hyx2001 | 2:f0fc57045b3d | 67 | if (__modbusFoundFrame) { |
hyx2001 | 2:f0fc57045b3d | 68 | __modbusIntervalCounter++; |
hyx2001 | 2:f0fc57045b3d | 69 | if (__modbusIntervalCounter > __modbusReturnInterval) { |
hyx2001 | 2:f0fc57045b3d | 70 | __modbusIntervalCounter = 0; |
hyx2001 | 2:f0fc57045b3d | 71 | __modbusFoundFrame = 0; |
hyx2001 | 2:f0fc57045b3d | 72 | modbusMainProcessing(); |
hyx2001 | 2:f0fc57045b3d | 73 | } |
hyx2001 | 2:f0fc57045b3d | 74 | } |
hyx2001 | 2:f0fc57045b3d | 75 | // 프레임 사이 블랭크 구간체크를 위한 카운터 업 |
hyx2001 | 2:f0fc57045b3d | 76 | if (__modbusBlankCheck < 0xffff) __modbusBlankCheck++; |
hyx2001 | 2:f0fc57045b3d | 77 | } |
hyx2001 | 2:f0fc57045b3d | 78 | |
hyx2001 | 2:f0fc57045b3d | 79 | void comfileHMI::push_ringbuffer(u8 comch, u8 comdt) |
hyx2001 | 2:f0fc57045b3d | 80 | { |
hyx2001 | 2:f0fc57045b3d | 81 | if (__modbusSwitch[comch]) { |
hyx2001 | 2:f0fc57045b3d | 82 | if (__modbusBlankCheck > 500) { |
hyx2001 | 2:f0fc57045b3d | 83 | comFlush(comch); // ^^ 500mS쉬었다 들어온 경우, 기존버퍼에 있던거는 모두 지운다. (노이즈 데이터일 가능성 있음) |
hyx2001 | 2:f0fc57045b3d | 84 | } |
hyx2001 | 2:f0fc57045b3d | 85 | __modbusBlankCheck = 0; |
hyx2001 | 2:f0fc57045b3d | 86 | } |
hyx2001 | 2:f0fc57045b3d | 87 | |
hyx2001 | 2:f0fc57045b3d | 88 | if(__save_pointer[comch]!=__action_pointer[comch]){ // 버퍼가 꽉차면 더이상 넣치 않는다. |
hyx2001 | 2:f0fc57045b3d | 89 | __ring_buffer[comch][__save_pointer[comch]]=comdt; |
hyx2001 | 2:f0fc57045b3d | 90 | __save_pointer[comch]++; |
hyx2001 | 2:f0fc57045b3d | 91 | if(__save_pointer[comch]>__ring_buffer_max) { |
hyx2001 | 2:f0fc57045b3d | 92 | __save_pointer[comch]=0; |
hyx2001 | 2:f0fc57045b3d | 93 | } |
hyx2001 | 2:f0fc57045b3d | 94 | } |
hyx2001 | 2:f0fc57045b3d | 95 | if (__modbusSwitch[comch]) modbusFrameSearch(comch); //수신직후 해당 채널이 모드버스 활성화 되어있으면 처리해준다. |
hyx2001 | 2:f0fc57045b3d | 96 | } |
hyx2001 | 2:f0fc57045b3d | 97 | |
hyx2001 | 2:f0fc57045b3d | 98 | u8 comfileHMI::read_ringbuffer(u8 comch) |
hyx2001 | 2:f0fc57045b3d | 99 | { |
hyx2001 | 2:f0fc57045b3d | 100 | __action_pointer[comch]++; |
hyx2001 | 2:f0fc57045b3d | 101 | if(__action_pointer[comch] > __ring_buffer_max){ |
hyx2001 | 2:f0fc57045b3d | 102 | __action_pointer[comch]=0; |
hyx2001 | 2:f0fc57045b3d | 103 | } |
hyx2001 | 2:f0fc57045b3d | 104 | return(__ring_buffer[comch][__action_pointer[comch]]); |
hyx2001 | 2:f0fc57045b3d | 105 | } |
hyx2001 | 2:f0fc57045b3d | 106 | |
hyx2001 | 2:f0fc57045b3d | 107 | /******************************************************************************* |
hyx2001 | 2:f0fc57045b3d | 108 | Function Name : comFlush [ 링버퍼 비우기 ] |
hyx2001 | 2:f0fc57045b3d | 109 | *******************************************************************************/ |
hyx2001 | 2:f0fc57045b3d | 110 | void comfileHMI::comFlush(u8 comch) |
hyx2001 | 2:f0fc57045b3d | 111 | { |
hyx2001 | 2:f0fc57045b3d | 112 | __action_pointer[comch] = __ring_buffer_max; |
hyx2001 | 2:f0fc57045b3d | 113 | __save_pointer[comch] = 0; |
hyx2001 | 2:f0fc57045b3d | 114 | } |
hyx2001 | 2:f0fc57045b3d | 115 | /******************************************************************************* |
hyx2001 | 2:f0fc57045b3d | 116 | Function Name : comLen [ ring buffer에 있는 데이터 량을 리턴 ] |
hyx2001 | 2:f0fc57045b3d | 117 | *******************************************************************************/ |
hyx2001 | 2:f0fc57045b3d | 118 | u16 comfileHMI::comLen(u8 comch) |
hyx2001 | 2:f0fc57045b3d | 119 | { |
hyx2001 | 2:f0fc57045b3d | 120 | u16 i; |
hyx2001 | 2:f0fc57045b3d | 121 | if (__save_pointer[comch]>(__action_pointer[comch]+1)) { |
hyx2001 | 2:f0fc57045b3d | 122 | i=__save_pointer[comch]-__action_pointer[comch]-1; |
hyx2001 | 2:f0fc57045b3d | 123 | } |
hyx2001 | 2:f0fc57045b3d | 124 | else if (__save_pointer[comch]<(__action_pointer[comch]+1)) { |
hyx2001 | 2:f0fc57045b3d | 125 | i=__ring_buffer_max-__action_pointer[comch]+__save_pointer[comch]; |
hyx2001 | 2:f0fc57045b3d | 126 | } |
hyx2001 | 2:f0fc57045b3d | 127 | else { |
hyx2001 | 2:f0fc57045b3d | 128 | i=0; |
hyx2001 | 2:f0fc57045b3d | 129 | } |
hyx2001 | 2:f0fc57045b3d | 130 | return(i); |
hyx2001 | 2:f0fc57045b3d | 131 | } |
hyx2001 | 2:f0fc57045b3d | 132 | /******************************************************************************* |
hyx2001 | 2:f0fc57045b3d | 133 | Function Name : comGet [ 1바이트 읽기 ] |
hyx2001 | 2:f0fc57045b3d | 134 | *******************************************************************************/ |
hyx2001 | 2:f0fc57045b3d | 135 | short comfileHMI::comGet(u8 comch) |
hyx2001 | 2:f0fc57045b3d | 136 | { |
hyx2001 | 2:f0fc57045b3d | 137 | if (comLen(comch) == 0) return -1; |
hyx2001 | 2:f0fc57045b3d | 138 | return read_ringbuffer(comch); |
hyx2001 | 2:f0fc57045b3d | 139 | } |
hyx2001 | 2:f0fc57045b3d | 140 | /******************************************************************************* |
hyx2001 | 2:f0fc57045b3d | 141 | Function Name : comGets [ n바이트 읽기 ] |
hyx2001 | 2:f0fc57045b3d | 142 | *******************************************************************************/ |
hyx2001 | 2:f0fc57045b3d | 143 | short comfileHMI::comGets(u8 comch, u8 * dest, u16 length) |
hyx2001 | 2:f0fc57045b3d | 144 | { |
hyx2001 | 2:f0fc57045b3d | 145 | u16 i; |
hyx2001 | 2:f0fc57045b3d | 146 | if (comLen(comch) == 0) return 0; |
hyx2001 | 2:f0fc57045b3d | 147 | for (i=0; i<length; i++) { |
hyx2001 | 2:f0fc57045b3d | 148 | dest[i] = read_ringbuffer(comch); |
hyx2001 | 2:f0fc57045b3d | 149 | } |
hyx2001 | 2:f0fc57045b3d | 150 | return -1; |
hyx2001 | 2:f0fc57045b3d | 151 | } |
hyx2001 | 2:f0fc57045b3d | 152 | |
hyx2001 | 2:f0fc57045b3d | 153 | /******************************************************************************* |
hyx2001 | 2:f0fc57045b3d | 154 | Function Name : comPut [ 1바이트 쓰기] |
hyx2001 | 2:f0fc57045b3d | 155 | *******************************************************************************/ |
hyx2001 | 2:f0fc57045b3d | 156 | |
hyx2001 | 2:f0fc57045b3d | 157 | |
hyx2001 | 2:f0fc57045b3d | 158 | void comfileHMI::comPut(u8 comch, u8 cha) |
hyx2001 | 2:f0fc57045b3d | 159 | { |
hyx2001 | 2:f0fc57045b3d | 160 | device->putc(cha); |
hyx2001 | 2:f0fc57045b3d | 161 | while(!device->writeable()); |
hyx2001 | 2:f0fc57045b3d | 162 | } |
hyx2001 | 2:f0fc57045b3d | 163 | |
hyx2001 | 2:f0fc57045b3d | 164 | /******************************************************************************* |
hyx2001 | 2:f0fc57045b3d | 165 | Function Name : comPuts [ n바이트 쓰기 ] |
hyx2001 | 2:f0fc57045b3d | 166 | *******************************************************************************/ |
hyx2001 | 2:f0fc57045b3d | 167 | void comfileHMI::comPuts(u8 comch, u8 * dest, u16 length) |
hyx2001 | 2:f0fc57045b3d | 168 | { |
hyx2001 | 2:f0fc57045b3d | 169 | u16 i; |
hyx2001 | 2:f0fc57045b3d | 170 | for (i=0; i<length; i++) { |
hyx2001 | 2:f0fc57045b3d | 171 | comPut(comch,dest[i]); |
hyx2001 | 2:f0fc57045b3d | 172 | } |
hyx2001 | 2:f0fc57045b3d | 173 | } |
hyx2001 | 2:f0fc57045b3d | 174 | |
hyx2001 | 2:f0fc57045b3d | 175 | u8 comfileHMI::mb_get_byte_rtu() |
hyx2001 | 2:f0fc57045b3d | 176 | { |
hyx2001 | 2:f0fc57045b3d | 177 | return read_ringbuffer(__modbusComCh); |
hyx2001 | 2:f0fc57045b3d | 178 | } |
hyx2001 | 2:f0fc57045b3d | 179 | |
hyx2001 | 2:f0fc57045b3d | 180 | u16 comfileHMI::mb_get_word_rtu() |
hyx2001 | 2:f0fc57045b3d | 181 | { |
hyx2001 | 2:f0fc57045b3d | 182 | u16 wi; |
hyx2001 | 2:f0fc57045b3d | 183 | wi = read_ringbuffer(__modbusComCh); |
hyx2001 | 2:f0fc57045b3d | 184 | wi <<= 8; |
hyx2001 | 2:f0fc57045b3d | 185 | wi += read_ringbuffer(__modbusComCh); |
hyx2001 | 2:f0fc57045b3d | 186 | return wi; |
hyx2001 | 2:f0fc57045b3d | 187 | } |
hyx2001 | 2:f0fc57045b3d | 188 | |
hyx2001 | 2:f0fc57045b3d | 189 | void comfileHMI::mb_inc_pointer() |
hyx2001 | 2:f0fc57045b3d | 190 | { |
hyx2001 | 2:f0fc57045b3d | 191 | (void)read_ringbuffer(__modbusComCh); |
hyx2001 | 2:f0fc57045b3d | 192 | } |
hyx2001 | 2:f0fc57045b3d | 193 | |
hyx2001 | 2:f0fc57045b3d | 194 | void comfileHMI::mb_put_byte_rtu(u8 dt) |
hyx2001 | 2:f0fc57045b3d | 195 | { |
hyx2001 | 2:f0fc57045b3d | 196 | comPut(__modbusComCh, dt); |
hyx2001 | 2:f0fc57045b3d | 197 | mb_crc_compute(dt); |
hyx2001 | 2:f0fc57045b3d | 198 | } |
hyx2001 | 2:f0fc57045b3d | 199 | |
hyx2001 | 2:f0fc57045b3d | 200 | // |
hyx2001 | 2:f0fc57045b3d | 201 | // Bit 읽기 RTU (FC 0,1) |
hyx2001 | 2:f0fc57045b3d | 202 | // |
hyx2001 | 2:f0fc57045b3d | 203 | const u8 mb_ncdtb[] = {1,2,4,8,16,32,64,128}; |
hyx2001 | 2:f0fc57045b3d | 204 | |
hyx2001 | 2:f0fc57045b3d | 205 | u8 comfileHMI::mb_collectbits(u16 adr) |
hyx2001 | 2:f0fc57045b3d | 206 | { |
hyx2001 | 2:f0fc57045b3d | 207 | u8 i,j,m=0; // adr은 modbus상의 주소, 이것을 실제주소로 환산하여 |
hyx2001 | 2:f0fc57045b3d | 208 | for (i=0;i<8;i++) { // 그곳에 있는 비트값을 8번 읽어, 한바이트의 데이터로 완성시켜준다. |
hyx2001 | 2:f0fc57045b3d | 209 | j = __modbusBitBuffer[adr>>3]; |
hyx2001 | 2:f0fc57045b3d | 210 | if (j & mb_ncdtb[adr & 7]) m |= mb_ncdtb[i]; |
hyx2001 | 2:f0fc57045b3d | 211 | adr++; |
hyx2001 | 2:f0fc57045b3d | 212 | } |
hyx2001 | 2:f0fc57045b3d | 213 | return m; |
hyx2001 | 2:f0fc57045b3d | 214 | } |
hyx2001 | 2:f0fc57045b3d | 215 | |
hyx2001 | 2:f0fc57045b3d | 216 | void comfileHMI::mbcmd_read_bit_rtu(u8 cmd) |
hyx2001 | 2:f0fc57045b3d | 217 | { |
hyx2001 | 2:f0fc57045b3d | 218 | u8 i,j,bln; |
hyx2001 | 2:f0fc57045b3d | 219 | u16 stadr,ln; |
hyx2001 | 2:f0fc57045b3d | 220 | stadr = mb_get_word_rtu(); // Start Address |
hyx2001 | 2:f0fc57045b3d | 221 | ln = mb_get_word_rtu(); // Length |
hyx2001 | 2:f0fc57045b3d | 222 | mb_inc_pointer(); |
hyx2001 | 2:f0fc57045b3d | 223 | mb_inc_pointer(); // CRC는 이미 체크했으므로 pass |
hyx2001 | 2:f0fc57045b3d | 224 | // 송신시작 |
hyx2001 | 2:f0fc57045b3d | 225 | if (__modbusBroadMode) return; // Brodecast 모드면 그냥 리턴 |
hyx2001 | 2:f0fc57045b3d | 226 | uchCRCHi = uchCRCLo = 0xff; // CRC 계산 start |
hyx2001 | 2:f0fc57045b3d | 227 | mb_put_byte_rtu(__modbusSlaveAdr); // Slave Address |
hyx2001 | 2:f0fc57045b3d | 228 | mb_put_byte_rtu(cmd); // Command |
hyx2001 | 2:f0fc57045b3d | 229 | bln = ln >> 3; |
hyx2001 | 2:f0fc57045b3d | 230 | if (ln & 7) bln++; // 나머지가 있으면 +1 |
hyx2001 | 2:f0fc57045b3d | 231 | mb_put_byte_rtu(bln); // Byte Count |
hyx2001 | 2:f0fc57045b3d | 232 | for (i=0; i<bln; i++) { |
hyx2001 | 2:f0fc57045b3d | 233 | j=mb_collectbits(stadr); |
hyx2001 | 2:f0fc57045b3d | 234 | mb_put_byte_rtu(j); |
hyx2001 | 2:f0fc57045b3d | 235 | stadr += 8; |
hyx2001 | 2:f0fc57045b3d | 236 | } |
hyx2001 | 2:f0fc57045b3d | 237 | i = uchCRCLo; // 바로 아래에서 uchCRCLo를 건드리기 때문에 Save해둔다. |
hyx2001 | 2:f0fc57045b3d | 238 | mb_put_byte_rtu(uchCRCHi); // CRC |
hyx2001 | 2:f0fc57045b3d | 239 | mb_put_byte_rtu(i); |
hyx2001 | 2:f0fc57045b3d | 240 | } |
hyx2001 | 2:f0fc57045b3d | 241 | |
hyx2001 | 2:f0fc57045b3d | 242 | // |
hyx2001 | 2:f0fc57045b3d | 243 | // 1 Bit 쓰기 (FC 5) |
hyx2001 | 2:f0fc57045b3d | 244 | // |
hyx2001 | 2:f0fc57045b3d | 245 | |
hyx2001 | 2:f0fc57045b3d | 246 | void comfileHMI::mbcmd_write_bit_single_rtu() |
hyx2001 | 2:f0fc57045b3d | 247 | { |
hyx2001 | 2:f0fc57045b3d | 248 | u8 i; |
hyx2001 | 2:f0fc57045b3d | 249 | u16 stadr,realadr,val; |
hyx2001 | 2:f0fc57045b3d | 250 | stadr = mb_get_word_rtu(); // Start Address |
hyx2001 | 2:f0fc57045b3d | 251 | val = mb_get_word_rtu(); // Write Value |
hyx2001 | 2:f0fc57045b3d | 252 | mb_inc_pointer(); // CRC는 이미 체크했으므로 pass |
hyx2001 | 2:f0fc57045b3d | 253 | mb_inc_pointer(); |
hyx2001 | 2:f0fc57045b3d | 254 | |
hyx2001 | 2:f0fc57045b3d | 255 | realadr = stadr >> 3; |
hyx2001 | 2:f0fc57045b3d | 256 | if (val) __modbusBitBuffer[realadr] |= mb_ncdtb[stadr & 7]; |
hyx2001 | 2:f0fc57045b3d | 257 | else __modbusBitBuffer[realadr] &= ~mb_ncdtb[stadr & 7]; |
hyx2001 | 2:f0fc57045b3d | 258 | // 송신시작 |
hyx2001 | 2:f0fc57045b3d | 259 | if (__modbusBroadMode) return; // Brodecast 모드면 그냥 리턴 |
hyx2001 | 2:f0fc57045b3d | 260 | uchCRCHi = uchCRCLo = 0xff; // CRC 계산 start |
hyx2001 | 2:f0fc57045b3d | 261 | mb_put_byte_rtu(__modbusSlaveAdr); // Slave Address |
hyx2001 | 2:f0fc57045b3d | 262 | mb_put_byte_rtu(5); // Command |
hyx2001 | 2:f0fc57045b3d | 263 | mb_put_byte_rtu(stadr >> 8); |
hyx2001 | 2:f0fc57045b3d | 264 | mb_put_byte_rtu(stadr); |
hyx2001 | 2:f0fc57045b3d | 265 | mb_put_byte_rtu(val >> 8); |
hyx2001 | 2:f0fc57045b3d | 266 | mb_put_byte_rtu(val); |
hyx2001 | 2:f0fc57045b3d | 267 | i = uchCRCLo; |
hyx2001 | 2:f0fc57045b3d | 268 | mb_put_byte_rtu(uchCRCHi); // CRC |
hyx2001 | 2:f0fc57045b3d | 269 | mb_put_byte_rtu(i); |
hyx2001 | 2:f0fc57045b3d | 270 | } |
hyx2001 | 2:f0fc57045b3d | 271 | |
hyx2001 | 2:f0fc57045b3d | 272 | // |
hyx2001 | 2:f0fc57045b3d | 273 | // MODBUS RTU Word Read (FC 3, 4) |
hyx2001 | 2:f0fc57045b3d | 274 | // |
hyx2001 | 2:f0fc57045b3d | 275 | |
hyx2001 | 2:f0fc57045b3d | 276 | void comfileHMI::mbcmd_read_word_rtu(u8 cmd) |
hyx2001 | 2:f0fc57045b3d | 277 | { |
hyx2001 | 2:f0fc57045b3d | 278 | u8 i; |
hyx2001 | 2:f0fc57045b3d | 279 | u16 stadr,ln,li,dt; |
hyx2001 | 2:f0fc57045b3d | 280 | stadr = mb_get_word_rtu(); // Start Address |
hyx2001 | 2:f0fc57045b3d | 281 | ln = mb_get_word_rtu(); // Length |
hyx2001 | 2:f0fc57045b3d | 282 | mb_inc_pointer(); |
hyx2001 | 2:f0fc57045b3d | 283 | mb_inc_pointer(); // CRC는 이미 체크되었으므로 pass |
hyx2001 | 2:f0fc57045b3d | 284 | // |
hyx2001 | 2:f0fc57045b3d | 285 | // Send Start |
hyx2001 | 2:f0fc57045b3d | 286 | // |
hyx2001 | 2:f0fc57045b3d | 287 | if (__modbusBroadMode) return; // Brodecast 모드면 그냥 리턴 |
hyx2001 | 2:f0fc57045b3d | 288 | uchCRCHi = uchCRCLo = 0xff; // CRC 계산 start |
hyx2001 | 2:f0fc57045b3d | 289 | mb_put_byte_rtu(__modbusSlaveAdr); // Slave Address |
hyx2001 | 2:f0fc57045b3d | 290 | mb_put_byte_rtu(cmd); // Command |
hyx2001 | 2:f0fc57045b3d | 291 | i = ln << 1; |
hyx2001 | 2:f0fc57045b3d | 292 | mb_put_byte_rtu(i); // Byte Count |
hyx2001 | 2:f0fc57045b3d | 293 | |
hyx2001 | 2:f0fc57045b3d | 294 | for (li=0; li<ln; li++) { |
hyx2001 | 2:f0fc57045b3d | 295 | dt = __modbusWordBuffer[stadr++]; |
hyx2001 | 2:f0fc57045b3d | 296 | mb_put_byte_rtu(dt >> 8); // High |
hyx2001 | 2:f0fc57045b3d | 297 | mb_put_byte_rtu(dt); // Low |
hyx2001 | 2:f0fc57045b3d | 298 | } |
hyx2001 | 2:f0fc57045b3d | 299 | i = uchCRCLo; |
hyx2001 | 2:f0fc57045b3d | 300 | mb_put_byte_rtu(uchCRCHi); // CRC |
hyx2001 | 2:f0fc57045b3d | 301 | mb_put_byte_rtu(i); |
hyx2001 | 2:f0fc57045b3d | 302 | } |
hyx2001 | 2:f0fc57045b3d | 303 | |
hyx2001 | 2:f0fc57045b3d | 304 | // |
hyx2001 | 2:f0fc57045b3d | 305 | // 1워드만 쓰기 (FC 6) |
hyx2001 | 2:f0fc57045b3d | 306 | // |
hyx2001 | 2:f0fc57045b3d | 307 | |
hyx2001 | 2:f0fc57045b3d | 308 | void comfileHMI::mbcmd_write_word_single_rtu() |
hyx2001 | 2:f0fc57045b3d | 309 | { |
hyx2001 | 2:f0fc57045b3d | 310 | //u8 lsave,i; |
hyx2001 | 2:f0fc57045b3d | 311 | //u16 stadr,realadr,val; |
hyx2001 | 2:f0fc57045b3d | 312 | u8 i; |
hyx2001 | 2:f0fc57045b3d | 313 | u16 stadr,val; |
hyx2001 | 2:f0fc57045b3d | 314 | stadr = mb_get_word_rtu(); // Start Address |
hyx2001 | 2:f0fc57045b3d | 315 | val = mb_get_word_rtu(); // Write Value |
hyx2001 | 2:f0fc57045b3d | 316 | mb_inc_pointer(); |
hyx2001 | 2:f0fc57045b3d | 317 | mb_inc_pointer(); // CRC는 이미 체크되었으므로 pass |
hyx2001 | 2:f0fc57045b3d | 318 | __modbusWordBuffer[stadr] = val; |
hyx2001 | 2:f0fc57045b3d | 319 | |
hyx2001 | 2:f0fc57045b3d | 320 | if (__modbusBroadMode) return; // Brodecast 모드면 그냥 리턴 |
hyx2001 | 2:f0fc57045b3d | 321 | uchCRCHi = uchCRCLo = 0xff; // CRC 계산 start |
hyx2001 | 2:f0fc57045b3d | 322 | mb_put_byte_rtu(__modbusSlaveAdr); // Slave Address |
hyx2001 | 2:f0fc57045b3d | 323 | mb_put_byte_rtu(6); // Command |
hyx2001 | 2:f0fc57045b3d | 324 | mb_put_byte_rtu(stadr >> 8); |
hyx2001 | 2:f0fc57045b3d | 325 | mb_put_byte_rtu(stadr); |
hyx2001 | 2:f0fc57045b3d | 326 | mb_put_byte_rtu(val >> 8); |
hyx2001 | 2:f0fc57045b3d | 327 | mb_put_byte_rtu(val); |
hyx2001 | 2:f0fc57045b3d | 328 | i = uchCRCLo; // 바로 아래에서 uchCRCLo를 건드리기 때문에 Save해둔다. |
hyx2001 | 2:f0fc57045b3d | 329 | mb_put_byte_rtu(uchCRCHi); // CRC |
hyx2001 | 2:f0fc57045b3d | 330 | mb_put_byte_rtu(i); |
hyx2001 | 2:f0fc57045b3d | 331 | } |
hyx2001 | 2:f0fc57045b3d | 332 | |
hyx2001 | 2:f0fc57045b3d | 333 | |
hyx2001 | 2:f0fc57045b3d | 334 | // |
hyx2001 | 2:f0fc57045b3d | 335 | // 연속으로 Bit 쓰기 RTU (FC 15) |
hyx2001 | 2:f0fc57045b3d | 336 | // |
hyx2001 | 2:f0fc57045b3d | 337 | |
hyx2001 | 2:f0fc57045b3d | 338 | void comfileHMI::mb_writebits(u16 adr, u8 val, u8 ln) |
hyx2001 | 2:f0fc57045b3d | 339 | { |
hyx2001 | 2:f0fc57045b3d | 340 | u8 i,m; |
hyx2001 | 2:f0fc57045b3d | 341 | if (ln > 7) m=8; |
hyx2001 | 2:f0fc57045b3d | 342 | else m=ln; // 15인 경우도 8개씩 나누어서 처리 |
hyx2001 | 2:f0fc57045b3d | 343 | for (i=0;i<m;i++) { // 8번 (마지막에서는 8번 미만) 돌면서, buffer의 내용을 수정한다. |
hyx2001 | 2:f0fc57045b3d | 344 | if (val & mb_ncdtb[i]) // (adr에 byte어드레스와 bit어드레스 모두 포함되어 있다.) |
hyx2001 | 2:f0fc57045b3d | 345 | __modbusBitBuffer[adr >> 3] |= mb_ncdtb[adr & 7]; |
hyx2001 | 2:f0fc57045b3d | 346 | else |
hyx2001 | 2:f0fc57045b3d | 347 | __modbusBitBuffer[adr >> 3] &= ~mb_ncdtb[adr & 7]; |
hyx2001 | 2:f0fc57045b3d | 348 | adr++; |
hyx2001 | 2:f0fc57045b3d | 349 | } |
hyx2001 | 2:f0fc57045b3d | 350 | } |
hyx2001 | 2:f0fc57045b3d | 351 | |
hyx2001 | 2:f0fc57045b3d | 352 | void comfileHMI::mbcmd_write_bit_multiple_rtu() |
hyx2001 | 2:f0fc57045b3d | 353 | { |
hyx2001 | 2:f0fc57045b3d | 354 | u8 i,j,cnt; |
hyx2001 | 2:f0fc57045b3d | 355 | u16 stadr,ln,lnsave,stadr_save; |
hyx2001 | 2:f0fc57045b3d | 356 | stadr_save = stadr = mb_get_word_rtu(); // Start Address |
hyx2001 | 2:f0fc57045b3d | 357 | lnsave = ln = mb_get_word_rtu(); // Length |
hyx2001 | 2:f0fc57045b3d | 358 | cnt = mb_get_byte_rtu(); // byte count |
hyx2001 | 2:f0fc57045b3d | 359 | for (i=0; i<cnt; i++) { |
hyx2001 | 2:f0fc57045b3d | 360 | j = mb_get_byte_rtu(); // value |
hyx2001 | 2:f0fc57045b3d | 361 | mb_writebits(stadr, j, ln); |
hyx2001 | 2:f0fc57045b3d | 362 | stadr += 8; |
hyx2001 | 2:f0fc57045b3d | 363 | ln -= 8; |
hyx2001 | 2:f0fc57045b3d | 364 | } |
hyx2001 | 2:f0fc57045b3d | 365 | mb_inc_pointer(); |
hyx2001 | 2:f0fc57045b3d | 366 | mb_inc_pointer(); // CRC는 이미 체크했으므로 pass |
hyx2001 | 2:f0fc57045b3d | 367 | // 송신시작 |
hyx2001 | 2:f0fc57045b3d | 368 | if (__modbusBroadMode) return; // Brodecast 모드면 그냥 리턴 |
hyx2001 | 2:f0fc57045b3d | 369 | uchCRCHi = uchCRCLo = 0xff; // CRC 계산 start |
hyx2001 | 2:f0fc57045b3d | 370 | mb_put_byte_rtu(__modbusSlaveAdr); // Slave Address |
hyx2001 | 2:f0fc57045b3d | 371 | mb_put_byte_rtu(15); // Command |
hyx2001 | 2:f0fc57045b3d | 372 | mb_put_byte_rtu(stadr_save >> 8); |
hyx2001 | 2:f0fc57045b3d | 373 | mb_put_byte_rtu(stadr_save); |
hyx2001 | 2:f0fc57045b3d | 374 | mb_put_byte_rtu(lnsave >> 8); |
hyx2001 | 2:f0fc57045b3d | 375 | mb_put_byte_rtu(lnsave); |
hyx2001 | 2:f0fc57045b3d | 376 | i = uchCRCLo; // 바로 아래에서 uchCRCLo를 건드리기 때문에 Save해둔다. |
hyx2001 | 2:f0fc57045b3d | 377 | mb_put_byte_rtu(uchCRCHi); // CRC |
hyx2001 | 2:f0fc57045b3d | 378 | mb_put_byte_rtu(i); |
hyx2001 | 2:f0fc57045b3d | 379 | } |
hyx2001 | 2:f0fc57045b3d | 380 | |
hyx2001 | 2:f0fc57045b3d | 381 | // |
hyx2001 | 2:f0fc57045b3d | 382 | // 연속으로 워드 쓰기 RTU (FC 16) |
hyx2001 | 2:f0fc57045b3d | 383 | // |
hyx2001 | 2:f0fc57045b3d | 384 | |
hyx2001 | 2:f0fc57045b3d | 385 | void comfileHMI::mbcmd_write_word_multiple_rtu() |
hyx2001 | 2:f0fc57045b3d | 386 | { |
hyx2001 | 2:f0fc57045b3d | 387 | u8 j; |
hyx2001 | 2:f0fc57045b3d | 388 | u16 stadr,realadr,val,ln,i; |
hyx2001 | 2:f0fc57045b3d | 389 | realadr = stadr = mb_get_word_rtu(); // Start Address |
hyx2001 | 2:f0fc57045b3d | 390 | ln = mb_get_word_rtu(); // length |
hyx2001 | 2:f0fc57045b3d | 391 | mb_inc_pointer(); // byte count |
hyx2001 | 2:f0fc57045b3d | 392 | for (i=0;i<ln;i++) { |
hyx2001 | 2:f0fc57045b3d | 393 | val = mb_get_word_rtu(); // Write Value |
hyx2001 | 2:f0fc57045b3d | 394 | __modbusWordBuffer[realadr++] = val; // 여기서 Write 실행 |
hyx2001 | 2:f0fc57045b3d | 395 | } |
hyx2001 | 2:f0fc57045b3d | 396 | mb_inc_pointer(); |
hyx2001 | 2:f0fc57045b3d | 397 | mb_inc_pointer(); // CRC는 이미 체크했으므로 pass |
hyx2001 | 2:f0fc57045b3d | 398 | // 송신시작 |
hyx2001 | 2:f0fc57045b3d | 399 | if (__modbusBroadMode) return; // Brodecast 모드면 그냥 리턴 |
hyx2001 | 2:f0fc57045b3d | 400 | uchCRCHi = uchCRCLo = 0xff; // CRC 계산 start |
hyx2001 | 2:f0fc57045b3d | 401 | mb_put_byte_rtu(__modbusSlaveAdr); // Slave Address |
hyx2001 | 2:f0fc57045b3d | 402 | mb_put_byte_rtu(16); // Command |
hyx2001 | 2:f0fc57045b3d | 403 | mb_put_byte_rtu(stadr >> 8); |
hyx2001 | 2:f0fc57045b3d | 404 | mb_put_byte_rtu(stadr); |
hyx2001 | 2:f0fc57045b3d | 405 | mb_put_byte_rtu(ln >> 8); |
hyx2001 | 2:f0fc57045b3d | 406 | mb_put_byte_rtu(ln); |
hyx2001 | 2:f0fc57045b3d | 407 | j = uchCRCLo; // 바로 아래에서 uchCRCLo를 건드리기 때문에 Save해둔다. |
hyx2001 | 2:f0fc57045b3d | 408 | mb_put_byte_rtu(uchCRCHi); // CRC |
hyx2001 | 2:f0fc57045b3d | 409 | mb_put_byte_rtu(j); |
hyx2001 | 2:f0fc57045b3d | 410 | } |
hyx2001 | 2:f0fc57045b3d | 411 | |
hyx2001 | 2:f0fc57045b3d | 412 | |
hyx2001 | 2:f0fc57045b3d | 413 | /******************************************************************************* |
hyx2001 | 2:f0fc57045b3d | 414 | |
hyx2001 | 2:f0fc57045b3d | 415 | Function Name : startModbus |
hyx2001 | 2:f0fc57045b3d | 416 | 모드버스 MAIN 처리 |
hyx2001 | 2:f0fc57045b3d | 417 | |
hyx2001 | 2:f0fc57045b3d | 418 | *******************************************************************************/ |
hyx2001 | 2:f0fc57045b3d | 419 | |
hyx2001 | 2:f0fc57045b3d | 420 | const u8 auchCRCH[] = { |
hyx2001 | 2:f0fc57045b3d | 421 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, |
hyx2001 | 2:f0fc57045b3d | 422 | 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, |
hyx2001 | 2:f0fc57045b3d | 423 | 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, |
hyx2001 | 2:f0fc57045b3d | 424 | 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, |
hyx2001 | 2:f0fc57045b3d | 425 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, |
hyx2001 | 2:f0fc57045b3d | 426 | 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, |
hyx2001 | 2:f0fc57045b3d | 427 | 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, |
hyx2001 | 2:f0fc57045b3d | 428 | 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, |
hyx2001 | 2:f0fc57045b3d | 429 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, |
hyx2001 | 2:f0fc57045b3d | 430 | 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, |
hyx2001 | 2:f0fc57045b3d | 431 | 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, |
hyx2001 | 2:f0fc57045b3d | 432 | 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, |
hyx2001 | 2:f0fc57045b3d | 433 | 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, |
hyx2001 | 2:f0fc57045b3d | 434 | 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, |
hyx2001 | 2:f0fc57045b3d | 435 | 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, |
hyx2001 | 2:f0fc57045b3d | 436 | 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, |
hyx2001 | 2:f0fc57045b3d | 437 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,0x40}; |
hyx2001 | 2:f0fc57045b3d | 438 | |
hyx2001 | 2:f0fc57045b3d | 439 | const u8 auchCRCL[] = { |
hyx2001 | 2:f0fc57045b3d | 440 | 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, |
hyx2001 | 2:f0fc57045b3d | 441 | 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, |
hyx2001 | 2:f0fc57045b3d | 442 | 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, |
hyx2001 | 2:f0fc57045b3d | 443 | 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, |
hyx2001 | 2:f0fc57045b3d | 444 | 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7, |
hyx2001 | 2:f0fc57045b3d | 445 | 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, |
hyx2001 | 2:f0fc57045b3d | 446 | 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, |
hyx2001 | 2:f0fc57045b3d | 447 | 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, |
hyx2001 | 2:f0fc57045b3d | 448 | 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, |
hyx2001 | 2:f0fc57045b3d | 449 | 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, |
hyx2001 | 2:f0fc57045b3d | 450 | 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, |
hyx2001 | 2:f0fc57045b3d | 451 | 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, |
hyx2001 | 2:f0fc57045b3d | 452 | 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91, |
hyx2001 | 2:f0fc57045b3d | 453 | 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, |
hyx2001 | 2:f0fc57045b3d | 454 | 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, |
hyx2001 | 2:f0fc57045b3d | 455 | 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, |
hyx2001 | 2:f0fc57045b3d | 456 | 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80,0x40}; |
hyx2001 | 2:f0fc57045b3d | 457 | |
hyx2001 | 2:f0fc57045b3d | 458 | void comfileHMI::mb_crc_compute(u8 rch) |
hyx2001 | 2:f0fc57045b3d | 459 | { |
hyx2001 | 2:f0fc57045b3d | 460 | uINDEX = uchCRCHi ^ rch; |
hyx2001 | 2:f0fc57045b3d | 461 | uchCRCHi = uchCRCLo ^ auchCRCH[uINDEX]; |
hyx2001 | 2:f0fc57045b3d | 462 | uchCRCLo = auchCRCL[uINDEX]; |
hyx2001 | 2:f0fc57045b3d | 463 | } |
hyx2001 | 2:f0fc57045b3d | 464 | |
hyx2001 | 2:f0fc57045b3d | 465 | // |
hyx2001 | 2:f0fc57045b3d | 466 | // CRC16을 얻기위한 함수, byte형 어레이에서 원하는 바이트수만큼 계산한뒤 그 결과값을 리턴 |
hyx2001 | 2:f0fc57045b3d | 467 | // |
hyx2001 | 2:f0fc57045b3d | 468 | |
hyx2001 | 2:f0fc57045b3d | 469 | u16 comfileHMI::getCrc(u8 * targetArray, u16 datalength) |
hyx2001 | 2:f0fc57045b3d | 470 | { |
hyx2001 | 2:f0fc57045b3d | 471 | u16 d; |
hyx2001 | 2:f0fc57045b3d | 472 | uchCRCHi = uchCRCLo = 0xff; // CRC 계산 start |
hyx2001 | 2:f0fc57045b3d | 473 | for (d=0; d<datalength; d++) { |
hyx2001 | 2:f0fc57045b3d | 474 | mb_crc_compute(targetArray[d]); |
hyx2001 | 2:f0fc57045b3d | 475 | } |
hyx2001 | 2:f0fc57045b3d | 476 | d = (uchCRCHi << 8) + uchCRCLo; |
hyx2001 | 2:f0fc57045b3d | 477 | return d; |
hyx2001 | 2:f0fc57045b3d | 478 | } |
hyx2001 | 2:f0fc57045b3d | 479 | |
hyx2001 | 2:f0fc57045b3d | 480 | // Register (워드저장소)의 시작번지와 |
hyx2001 | 2:f0fc57045b3d | 481 | // Coil (비트저장소)의 시작번지를 건네 받는다. |
hyx2001 | 2:f0fc57045b3d | 482 | // 응답 간격은 대략 3mS |
hyx2001 | 2:f0fc57045b3d | 483 | |
hyx2001 | 2:f0fc57045b3d | 484 | void comfileHMI::startSimpleModbus(u8 comch, u8 modslaveadr, u16 * modbusBufferRegister, u8 * modbusBufferCoil) |
hyx2001 | 2:f0fc57045b3d | 485 | { |
hyx2001 | 2:f0fc57045b3d | 486 | __modbusComCh = comch; |
hyx2001 | 2:f0fc57045b3d | 487 | __modbusSlaveAdr = modslaveadr; |
hyx2001 | 2:f0fc57045b3d | 488 | __modbusSwitch[0] = 0; |
hyx2001 | 2:f0fc57045b3d | 489 | __modbusSwitch[1] = 0; |
hyx2001 | 2:f0fc57045b3d | 490 | __modbusSwitch[2] = 0; |
hyx2001 | 2:f0fc57045b3d | 491 | __modbusSwitch[3] = 0; |
hyx2001 | 2:f0fc57045b3d | 492 | __modbusSwitch[comch] = 1; // On, 4개 채널중 한개만 사용가능 |
hyx2001 | 2:f0fc57045b3d | 493 | __modbusWordBuffer = modbusBufferRegister; |
hyx2001 | 2:f0fc57045b3d | 494 | __modbusBitBuffer = modbusBufferCoil; |
hyx2001 | 2:f0fc57045b3d | 495 | } |
hyx2001 | 2:f0fc57045b3d | 496 | |
hyx2001 | 2:f0fc57045b3d | 497 | // |
hyx2001 | 2:f0fc57045b3d | 498 | // 1바이트 수신이 되었을때, 모드버스 RTU 프레임을 완성 (끝에 CRC가 앞에거와 일치)하는지 여부를 조사한다. |
hyx2001 | 2:f0fc57045b3d | 499 | // |
hyx2001 | 2:f0fc57045b3d | 500 | |
hyx2001 | 2:f0fc57045b3d | 501 | void comfileHMI::modbusFrameSearch(u8 comch) |
hyx2001 | 2:f0fc57045b3d | 502 | { |
hyx2001 | 2:f0fc57045b3d | 503 | u8 uch, ucl, bh, bl; |
hyx2001 | 2:f0fc57045b3d | 504 | u16 mclen, i; |
hyx2001 | 2:f0fc57045b3d | 505 | u16 uix; |
hyx2001 | 2:f0fc57045b3d | 506 | u16 save_pointer; |
hyx2001 | 2:f0fc57045b3d | 507 | mclen = comLen(comch); // 수신된 바이트 수 |
hyx2001 | 2:f0fc57045b3d | 508 | |
hyx2001 | 2:f0fc57045b3d | 509 | if (mclen < 8) return; // 8바이트 보다 적은 코멘드는 없으므로 바로 리턴 |
hyx2001 | 2:f0fc57045b3d | 510 | |
hyx2001 | 2:f0fc57045b3d | 511 | uch = ucl = 0xff; // 이제 CRC를 계산하기 시작.. 이것을 위해 링버퍼를 스캔한다. |
hyx2001 | 2:f0fc57045b3d | 512 | save_pointer = __action_pointer[comch]; // 실행지점 포인터를 카피 |
hyx2001 | 2:f0fc57045b3d | 513 | for (i = 0; i< mclen-2; i++) { |
hyx2001 | 2:f0fc57045b3d | 514 | uix = uch ^ mb_get_byte_rtu(); // __action_pointer를 건드리므로 나중에 복구해주어야 한다. |
hyx2001 | 2:f0fc57045b3d | 515 | uch = ucl ^ auchCRCH[uix]; |
hyx2001 | 2:f0fc57045b3d | 516 | ucl = auchCRCL[uix]; |
hyx2001 | 2:f0fc57045b3d | 517 | } |
hyx2001 | 2:f0fc57045b3d | 518 | bh = mb_get_byte_rtu(); //이것이 CRC값 |
hyx2001 | 2:f0fc57045b3d | 519 | bl = mb_get_byte_rtu(); |
hyx2001 | 2:f0fc57045b3d | 520 | __action_pointer[comch] = save_pointer; // 복구 |
hyx2001 | 2:f0fc57045b3d | 521 | |
hyx2001 | 2:f0fc57045b3d | 522 | if ((bh == uch) && (bl == ucl)) __modbusFoundFrame = 1; // 발견! |
hyx2001 | 2:f0fc57045b3d | 523 | |
hyx2001 | 2:f0fc57045b3d | 524 | } |
hyx2001 | 2:f0fc57045b3d | 525 | |
hyx2001 | 2:f0fc57045b3d | 526 | void comfileHMI::modbusMainProcessing() |
hyx2001 | 2:f0fc57045b3d | 527 | { |
hyx2001 | 2:f0fc57045b3d | 528 | u8 fc,sladr; |
hyx2001 | 2:f0fc57045b3d | 529 | sladr = mb_get_byte_rtu(); // 슬레이브 어드레스 읽어오기 |
hyx2001 | 2:f0fc57045b3d | 530 | if (sladr == 0) { |
hyx2001 | 2:f0fc57045b3d | 531 | __modbusBroadMode = 1; // 슬레이브 어드레스가 0이면 브로드케스트 모드 = 1 |
hyx2001 | 2:f0fc57045b3d | 532 | } |
hyx2001 | 2:f0fc57045b3d | 533 | else { |
hyx2001 | 2:f0fc57045b3d | 534 | if (sladr != __modbusSlaveAdr) { // 슬레이브 어드레스가 일치하지 않으면, 버퍼 클리어후 리턴 |
hyx2001 | 2:f0fc57045b3d | 535 | comFlush(__modbusComCh); |
hyx2001 | 2:f0fc57045b3d | 536 | return; |
hyx2001 | 2:f0fc57045b3d | 537 | } |
hyx2001 | 2:f0fc57045b3d | 538 | } |
hyx2001 | 2:f0fc57045b3d | 539 | |
hyx2001 | 2:f0fc57045b3d | 540 | fc = mb_get_byte_rtu(); // 펑션코드 읽어오기 |
hyx2001 | 2:f0fc57045b3d | 541 | |
hyx2001 | 2:f0fc57045b3d | 542 | //comPut(0, sladr); |
hyx2001 | 2:f0fc57045b3d | 543 | //comPut(0, fc); |
hyx2001 | 2:f0fc57045b3d | 544 | |
hyx2001 | 2:f0fc57045b3d | 545 | switch (fc) { |
hyx2001 | 2:f0fc57045b3d | 546 | case 1: |
hyx2001 | 2:f0fc57045b3d | 547 | case 2: |
hyx2001 | 2:f0fc57045b3d | 548 | mbcmd_read_bit_rtu(fc); |
hyx2001 | 2:f0fc57045b3d | 549 | break; |
hyx2001 | 2:f0fc57045b3d | 550 | case 3: |
hyx2001 | 2:f0fc57045b3d | 551 | case 4: |
hyx2001 | 2:f0fc57045b3d | 552 | mbcmd_read_word_rtu(fc); |
hyx2001 | 2:f0fc57045b3d | 553 | break; |
hyx2001 | 2:f0fc57045b3d | 554 | case 5: |
hyx2001 | 2:f0fc57045b3d | 555 | mbcmd_write_bit_single_rtu(); |
hyx2001 | 2:f0fc57045b3d | 556 | break; |
hyx2001 | 2:f0fc57045b3d | 557 | case 6: |
hyx2001 | 2:f0fc57045b3d | 558 | mbcmd_write_word_single_rtu(); |
hyx2001 | 2:f0fc57045b3d | 559 | break; |
hyx2001 | 2:f0fc57045b3d | 560 | case 15: |
hyx2001 | 2:f0fc57045b3d | 561 | mbcmd_write_bit_multiple_rtu(); |
hyx2001 | 2:f0fc57045b3d | 562 | break; |
hyx2001 | 2:f0fc57045b3d | 563 | case 16: |
hyx2001 | 2:f0fc57045b3d | 564 | mbcmd_write_word_multiple_rtu(); |
hyx2001 | 2:f0fc57045b3d | 565 | break; |
hyx2001 | 2:f0fc57045b3d | 566 | default: |
hyx2001 | 2:f0fc57045b3d | 567 | comFlush(__modbusComCh); // 없는 FC(펑션코드)일경우, 버퍼클리어 |
hyx2001 | 2:f0fc57045b3d | 568 | return; |
hyx2001 | 2:f0fc57045b3d | 569 | } |
hyx2001 | 2:f0fc57045b3d | 570 | } |
hyx2001 | 2:f0fc57045b3d | 571 | |
hyx2001 | 2:f0fc57045b3d | 572 | |
hyx2001 | 2:f0fc57045b3d | 573 |