OBDII Interface Project Source Code
http://www.oocities.org/sstandfast/OBDII.htm 1 // File: VPWM.jal
// Author: Shawn Standfast
// Version 1.00.2
// 11/1/2005
// Library for OBDII Variable Pulse Width Modulation on PIC16F877(A) @ 20MHz
//
// *Note - This library utilizes the CCPX Module, Timer 1, Timer 2 W/ Interrupts
// Also, be sure to be in Bank 0 before using any procedures in this
// library.
//
// This library is designed around the SAE J1850 VPWM standard. It is assumed
// that the bus is a CSMA/CR (Carrier Sense, Multiple Access, Collision Resolution)
// type bus. Ultimate bus control is determined by bit-by-bit arbitration. The
// general message format used is SOF + 1 or 3 Header Bytes + 10 or 8 Data Bytes
// + 1 CRC Byte + EOD + EOF. Max Frame Length = 12 Bytes
//
// Nominal Pulse widths are as follows:
// +-----------+--------------+
// | SYMBOL | Pulse Width |
// |-----------+--------------+
// | Active 1 | 64uS |
// | Passive 0 | 64uS |
// | |
// | Passive 1 | 128uS |
// | Active 0 | 128uS |
// | |
// | SOF | 200uS |
// | EOD | 200uS |
// | |
// | EOF | 280-300uS |
// +-----------+--------------+
// Functions: vpw_send(byte in data) return bit
// Procedures: vpw_receive()
// get_frame(byte in frame_num)
//
// I/O Pin Definitions and Directions
//
// pin_c2_direction = input
// pin_c1_direction = output
//
// vpwin is pin_c2
// vpwout is pin_c1 // Required Libraries:
include jpic // Set Bounds for Buffer Arrays
const array_check_indices = true const array0_start = 0xA0 // Output Array Start
const array0_end = 0xAC // Output Array End
const array1_start = 0xAD // Input Buffer Array 1 Start
const array1_end = 0xB9 // Input Buffer Array 1 End
const array2_start = 0xBA // Input Buffer Array 2 Start
const array2_end = 0xC6 // Input Buffer Array 2 End
const array3_start = 0xC7 // Input Buffer Array 3 Start
const array3_end = 0xD3 // Input Buffer Array 3 End
const array4_start = 0xD4 // Processing Buffer Array Start
const array4_end = 0xE0 // Processing Buffer Array End include bank_arrays // Other Constants
const rising = 0x05 // configure for capture on rising edge
const falling = 0x04 // configure for capture on falling edge
const per_short = 0x50 // number of cycles for 64uS for tmr1
const per_long = 0xA0 // number of cycles for 128uS for tmr1
const per_sof = 0xFA // number of cycles for 200uS for tmr1
const per_eof = 0xAF // #cycles 280uS, must use 1:8 prescaler for EOF detection
const comp_drive_low = 0x09 // for ccp2con to drive CCP2 pin low on compare
const comp_drive_high = 0x08 // for ccp2con to drive CCP2 pin high on compare
const comp_only = 0x0A // for ccp2con to flag only // I/O Pin Definitions and Directions
pin_c2_direction = input
pin_c1_direction = output
var bit vpwin is pin_c2
var bit vpwout is pin_c1
vpwout = false // Some Variables
// Byte Variables RESERVED FOR INTERRUPT ROUTINE
var byte tmr1_low_old = 0x00, tmr1_high_old = 0x00 // stores old tmr1 values
var byte tmr1_low_new = 0x00, tmr1_high_new = 0x00 // stores new tmr1 values
var byte delta_low = 0x00, delta_high = 0x00 // stores the difference between
// tmr1_old & tmr1_new
var bit pulse_rec = off // Configure ccpXmodule //--------------------------------------------------------
f877_ccp1con = 0x00
f877_ccp2con = 0x00 f877_ccpr2l = 0x00
f877_ccpr2h = 0x00 f877_ccpr1l = 0x00
f877_ccpr1h = 0x00 pir1_ccp1if = false // clear both CCP interrupt flags
pir2_ccp2if = false // Initialize Timer1------------------------------------------------------------
//
// max frame width = SOF + 11*(8 Data Bits) + 1 CRC Byte + EOF
// SOF = 200uS
// EOF = 300uS
// Max Byte Width (longest byte = 0b_1010_1010) = 128uS*8 = 1.024mS
// Max Data Width = 12*1024mS = 12.288mS
// max frame width = 12.788mS
// tmr1 overflows w/ a 1:4 prescaler @ 52.4288mS ample room for an entire frame
//
// //--------------------------------------------------------------------------- f877_t1con = 0x00 // 1:4 prescaler for timer1
t1ckps1 = on
tmr1if = false // clear interupt flag
f877_tmr1h = 0x00
f877_tmr1l = 0x00 // Initialize Timer 2 // --------------------------------------------------------
f877_t2con = 0x02 // 1:16 prescaler 1:1 postscaler for timer2
f877_tmr2 = 0x00 pir1_tmr2if = false // Initialize Periphial Interrupts // ------------------------------------------- asm BSF STATUS, // bank 1
tmr1ie = off // disable tmr1 interupt flag
pie1_ccp1ie = on // enable ccp1 interrupt flag
pie2_ccp2ie = off // disable ccp2 interrupt flag
pie1_tmr2ie = off // disable timer2 interrupts
f877_pr2 = 0x58
asm BCF STATUS, // bank 0 // disable interrupts //--------------------------------------------------------- intcon_gie = off
intcon_peie = off // vpw_idle_chk is for internal use to check for inactivity on the Com. Bus
procedure vpw_idle_chk is
tmr1on = false
vpwout = false // make sure only transmitting a low signal
pir2_ccp2if = false
t1ckps1 = on
t1ckps0 = on // set 1:8 prescaler for timer1 f877_tmr1l = 0x00 // reset timer one high and low bytes
f877_tmr1h = 0x00 f877_ccpr2l = per_eof // set period for compare to be ~280uS
f877_ccpr2h = 0x00 f877_ccp2con = comp_only // set CCP2 module to only flag when timer times out while vpwin loop end loop // loop until bus transisitions low tmr1on = on // start timer while ! pir2_ccp2if loop // wait while bus is low
if vpwin then // if activity detected on bus restart timer
f877_tmr1l = 0x00 // no need to reset high byte
end if
end loop pir2_ccp2if = false // clear interrupt flag tmr1on = false // stop timer 1 f877_tmr1l = 0x00 // reset timer 1
f877_tmr1h = 0x00 t1ckps0 = false // 1:4 prescaler for timer1
end procedure procedure crc_calc(byte in data, byte in out crc ) is // calculates the CRC byte
var byte bit_point = 0x80 // that is appended to the end of the OBD message Frame
var byte poly // NOTE* Procedure is to be called continuously for each
for loop // byte that is transmitted. However, once final byte is
if (bit_point & data) != then // passed through the CRC routine the final result in crc_reg
if (crc & 0x80) != then // must be complimented before appending to the message.
poly = 0x01 // For all messages, paramater CRC should be initialized to
else // 0xFF for the first itteration.
poly = 0x1C
end if
crc = ((crc << ) | ) ^ poly // original C Code for CRC posted on http:// obddiagnostics.com by B. Roadman
else // adapted to JAL by Shawn Standfast
poly = 0x00
if (crc & 0x80) != then
poly = 0x1D
end if
crc = (crc << ) ^ poly
end if
bit_point = bit_point >>
end loop
end procedure // Function vpw_send(byte in data) shifts out "data" one bit at a time
// MSB first. Arbritration is taken care of during transmission. If the
// transmission is successful then the function returns true else it returns
// false. Call procedure repeatedly to send multiple bytes. just be sure to
// only send one start of frame symbol per message frame. // Example Usage: *success is a var of type bit
// Send Single byte of data: success = vpw_send(data,true)
// tmr1on = false
// Send Multiple bytes in the same frame: success = vpw_send(data1,true)
// if success then
// success = vpw_send(data2,false)
// end if
// tmr1on = false
// Send "Array" of data:
// var bit send_sof = true
// var byte count = 0x00
// while ((success) & (count < arrayX_put_index)) loop
// temp = arrayX
// success = vpw_send(temp,send_sof)
// send_sof = false
// count = count + 1
// end loop
// tmr1on = false function vpw_send (byte in data, bit in send_sof) return bit is
asm bcf intcon_gie // disables interrupts while sending. otherwise we can get
asm bcf intcon_peie // into all sorts of trouble. :)
f877_ccp1con = 0x00
var bit error_flag = false
var volatile bit bit_out at data : // select bit to be transmitted
var bit dom_pass = false // keep track of active or passive symbol
var byte timer_low_byte, timer_high_byte, prtc_buf
var volatile byte next_bit = 0x00 // sets next pulse width for loop // shift data out one bit at a time; MSB first if bit_out then // if bit to be sent is a One
if dom_pass then // send "Active" One
next_bit = per_short
else // send "Passive" One
next_bit = per_long
end if
else // Bit to be sent is a Zero
if dom_pass then // send active zero
next_bit = per_long
else // send "Passive" zero
next_bit = per_short
end if
end if
// start of frame takes care of period adjustment for first bit. If current
// itteration is not sending a SOF, must adjust new period by adding pulse width
// to current ccp2H:ccp2L registers. if send_sof then // need to send a start of frame first?
// send start of frame plus first bit
vpw_idle_chk // verify bus is idle before beginning transmission f877_ccp2con = comp_drive_low // bus will be high for SOF. Drive bus low
// when pulse width is achieved. should also
// drive output pin high beginning transmission tmr1on = on // begin timing bus position f877_ccpr2l = per_sof // set period for compare to be ~200uS
f877_ccpr2h = 0x00 pir2_ccp2if = false error_flag = false // assume success unless failure occurs while ! pir2_ccp2if loop end loop // wait until timer2 times out. Once
// this loop is exited our SOF symbol
// will have finished and our output
// pin will be low.
// If the bus is still active then that means another node is still
// transmitting. The only other allowed active symbol that lasts for
// this duration is a BREAK symbol. So we poll the bus for the shortest
// allowed BREAK time. If this is passed then we will cease our attempt
// to transmit.
while vpwin loop // allows for nodes with slower clocks to finish their
assembler // SOF's.
local shorter
movf f877_tmr1h,w // The new starting point for the compare register
movwf f877_ccpr2h // is updated while the other nodes finish.
movf f877_tmr1l,w
movwf f877_ccpr2l
movf f877_tmr1h,w // ensures proper loading of CCP2 with the current
movwf f877_ccpr2h // timer value
bcf status_Z
movlw 0x01
subwf f877_ccpr2h,w // magnitude comparison of the current high byte
BTFSS status_Z // if the current timer value is greater than
GOTO shorter // 0x128 then the maximum allowed transmission
movlw 0x28 // length for a SOF has been reached. If it isnt
bsf status_C
subwf f877_ccpr2l,w // then we need to poll the bus again and repeat.
BTFSS status_C
GOTO shorter
bsf error_flag
shorter:
end assembler
if error_flag then
vpwout = false
tmr1on = false
f877_tmr1l = 0x00
f877_tmr1h = 0x00
f877_ccp2con = 0x00
return false
end if
end loop // SOF is always followed by data bytes. Prep for first bit to be sent
assembler // add next period to compare reference, 8-bit + 16-bit
bank MOVF next_bit,W
bank ADDWF f877_ccpr2l,f
BTFSC status_C
bank INCF f877_ccpr2h,f
end assembler asm clrf f877_ccp2con // first bit to be transmitted is always low
f877_ccp2con = comp_drive_high // set ccp2 to drive output high on match pir2_ccp2if = false // reset interrupt flag
send_sof = false // no more start of frame symbols to transmit
else // just send the remaining bits
assembler // add next period to compare reference. 8-bit + 16-bit
bank MOVF next_bit,W
bank ADDWF f877_ccpr2l,f
BTFSC status_C
bank INCF f877_ccpr2h,f
end assembler
end if while ! pir2_ccp2if loop // wait until end of period, when loop is
// exited bus transition should be done.
prtc_buf = port_c // Check for arbitration. If output does not
prtc_buf = prtc_buf & 0x06 // match input then arbitration may be lost.
if ((prtc_buf == 0x04) & (! pir2_ccp2if)) then
assembler
bcf tmr1on // Comparison between the bus transition time
// and the time remaining before bus expected
// transition is used to compensate for clock
// mismatch. Therefore false "lost arbritration"
// is avoided. This portion only checks for nodes
// that transition early. Nodes that transition
// later are dealt with after this portion.
bsf status_C
bcf status_Z local EXITE, EXIT
MOVF f877_tmr1l,W // determine delta between expected transition
SUBWF f877_ccpr2l,w // and actual transition time.
movwf timer_low_byte // timer_X_byte = ccpr2X - f877_tmr1X
MOVF f877_tmr1h,W
BTFSS status_C
INCF f877_tmr1h,W
SUBWF f877_ccpr2h,w
movwf timer_high_byte
btfss status, status_z // the difference between high bytes must be zero
goto EXITE
movlw 0x14 // to be within tolerance the difference must be less
bsf status_C // than 20 instructions. Setting the Carry/Borrow bit
subwf timer_low_byte,w // makes it available to borrow.
BTFSS status_C // If the low byte is >= 20 then a borrow
goto EXIT // will not have occured and status_c will still be set.
BTFSC status_Z // If the result is 0 then transition occured right on
goto EXIT // the boundary and is still valid.
EXITE: // check somewhere has not passed.
bsf error_flag
EXIT:
end assembler
if (error_flag) then // bus dominance lost.
vpwout = false // "Shut up and try again later"
tmr1on = false
f877_tmr1l = 0x00
f877_tmr1h = 0x00
f877_ccp2con = 0x00
return false
else // early transitioning node transitioned within specs. Change
f877_tmr1l = f877_ccpr2l // output and move on.
f877_tmr1h = f877_ccpr2h
tmr1on = on
end if
end if
if ((prtc_buf == 0x02) & (! pir2_ccp2if)) then // bus fault has been detected. Try again later.
vpwout = false
tmr1on = false
f877_tmr1l = 0x00
f877_tmr1h = 0x00
f877_ccp2con = 0x00
return false
end if
end loop pir2_ccp2if = false // reset ccp2 interrupt flag if dom_pass then // switch transition directions
// first must allow for nodes that are transmitting their active signals
// for just a little bit longer than we are. For the short pulse, the
// maximum allowed overshoot in time is 32uS and for the long pulse the
// maximum allowed overshoot in time is 34uS. Splitting the difference
// we will check for 33uS. However, I believe this to be incorrect and used 16uS.
if vpwin then // bus is still active
assembler
local loop1, done, exita
movlw comp_only
movwf f877_ccp2con
MOVlW 0x14
bank ADDWF f877_ccpr2l,f
BTFSC status_C
bank INCF f877_ccpr2h,f
loop1:
BTFSS vpwin // loops until either the input pin changes
goto done // or our "added" time expires.
BTFSS pir2_ccp2if
goto loop1
bcf tmr1on // if the program gets here then that means the input
bcf vpwout // is still set and our timer period has expired. If
clrf f877_tmr1l // we were sending a short pulse then it means arbitration
clrf f877_tmr1h // has been lost. If it is a long pulse then it could
clrf f877_ccp2con // mean a break symbol is being transmitted. Either way
bsf error_flag // we need to stop transmitting and exit.
bcf pir2_ccp2if
goto exita
done:
clrf f877_ccp2con // updates the compare registers with new
movf f877_tmr1h,w // starting values
movwf f877_ccpr2h
movf f877_tmr1l,w
movwf f877_ccpr2l
movf f877_tmr1h,w
movwf f877_ccpr2h
bcf pir2_ccp2if
exita:
end assembler
if error_flag then
return false
end if
end if
f877_ccp2con = comp_drive_high // if previously sending an active signal
dom_pass = false // next symbol will be passive. Ergo need
else // to drive bus high on next compare.
f877_ccp2con = comp_drive_low // Same logic here just opposite results
dom_pass = on // No need to check for devices with "longer"
end if // periods here because we have driven the
// bus high already.
data = data << // shift in next bit to be sent
end loop
return true
end function // procedure vpw_receive configures the ccp1 module to capture timer 1 and timer2
// to time inactivity. First ccp1 is configured to interrupt on the rising
// edge. On the first rising edge, timer 1 is started and the ccp1 module is
// reset for falling edge int. On the following edge interrupts, the two different
// captured timer 1 values are subtracted from each other to determine the
// pulse witdh. Then based upon which direction of the interrupting edge, the
// symbol is decoded. Once a SOF character has been decoded timer2 is enabled to start
// counting out 280uS to determine if IFS has been satisfied. Timer2 is reset
// on each valid pulse received. Therefore, timer2 clocks 280uS from the last bit received.
// Once a bit is received, it is placed in a bit buffer that is shifted left
// after each bit. When 8 bits have been received, that byte is placed into
// the first available frame buffer array. // ***NOTE*** In-Frame Response has NOT been implimented yet!! If you are using
// this library for a VPW system that requires IFR then you will need to add it.
// I will get around to adding it sometime in the near future but right now I do
// not need it (GM doesn't use IFR).
// //-------------------------------------------------------------------------- function vpw_receive return bit is var byte delta_low_old = 0x00, delta_high_old = 0x00 // buffers delta bytes
var volatile byte rec_buff = 0x00 // buffers the current received byte before
// loading into the buffer array
var byte bit_count = 0x00 // counts number of bits received
var volatile bit bit_rec = false // holds current received bit
var volatile bit data_rec = false // determines whether data has been received
var volatile bit bit_buff at rec_buff : // stores current received bit
var volatile bit long_short = false // flag indicating long or short pulse
var volatile bit brk_rec = false // flag indicating a BRK symbol has been received
var volatile byte ccpconfig = 0x00 // stores current ccp1 configuration
var volatile bit sof_rec = false f877_tmr1l = 0x00 // reset timer 1
f877_tmr1h = 0x00
tmr1_low_old = 0x00 // reset tmr1 storage variables
tmr1_high_old = 0x00
array4_put_index = 0x00 // reset processing buffer index to 0
pulse_rec = false
f877_ccp2con = 0x00 intcon_gie = on // enable interrupts
intcon_peie = on pir1_tmr2if = false vpw_idle_chk // wait until beginning of next frame before starting to receive asm clrf f877_ccp1con
f877_ccp1con = rising while ! pir1_tmr2if loop
while ! pulse_rec loop end loop
pulse_rec = false
delta_low_old = delta_low // buffer the delta values incase interrupt occurs
delta_high_old = delta_high // before we finish working with this pulse
ccpconfig = f877_ccp1con // buffer ccp1 configuration incase interrupt
// occurs before we finish working with this pulse if ((delta_high_old == 0x00) ) then
if delta_low_old >= 0xCC then
sof_rec = on
tmr2on = on
bit_count = 0x00
f877_tmr2 = 0x00
array4_put_index = 0x00
elsif ((delta_low_old <= 0xCB) & (delta_low_old >= 0x78)) then
long_short = on
data_rec = on
f877_tmr2 = 0x00
elsif ((delta_low_old <= 0x77) & (delta_low_old >= 0x2A)) then
long_short = off
data_rec = on
f877_tmr2 = 0x00
else
data_rec = false
end if
elsif ((delta_high_old == 0x01) ) then
if ((delta_low_old >= 0x2B) & (! pir1_tmr2if)) then
brk_rec = on
sof_rec = false
data_rec = false
long_short = false
tmr1on = false
tmr2on = false
f877_tmr1l = 0x00
f877_tmr1h = 0x00
f877_tmr2 = 0x00
array4_put_index = 0x00
tmr1_low_old = 0x00
tmr1_high_old = 0x00
delta_low_old = 0x00
delta_high_old = 0x00
asm clrf f877_ccp1con
f877_ccp1con = rising
elsif delta_low_old < 0x2B then
sof_rec = on
tmr2on = on
pir1_tmr2if = false
bit_count = 0x00
f877_tmr2 = 0x00
array4_put_index = 0x00
end if
end if
if data_rec & sof_rec then
if ccpconfig == rising then // if the next interrupt edge will be rising
if long_short then // then that means the previous pulse was active.
bit_rec = off // that means a long pulse = 0 and a short pulse = 1
else
bit_rec = on
end if
else // next interrupt edge will be falling, indicating the
if long_short then // previous pulse was passive. long_pulse = 1 & short_pulse = 0
bit_rec = on
else
bit_rec = off
end if
end if
rec_buff = rec_buff <<
bit_buff = bit_rec
data_rec = false
bit_count = bit_count +
end if
if bit_count == 0x08 then
array4 = rec_buff
bit_count = 0x00
end if
end loop
tmr1on = false
tmr2on = false
f877_ccp1con = 0x00
f877_tmr1l = 0x00
f877_tmr1h = 0x00
f877_tmr2 = 0x00
pir1_tmr2if = false
pir1_ccp1if = false intcon_gie = false
intcon_peie = false
return brk_rec
end function // Table for determining pulse widths from delta values:
// |long pulse| short pulse| SOF | break |
// | max | min | max | min | max | min | max | min |
// delta_high |0x00 | 0x00| 0x00 | 0x00| 0x01| 0x00| 0x01| 0x01|
// delta_low |0xCC | 0x78| 0x78 | 0x2A| 0x2B| 0xCC| 0x2B| 0x2B|
//
// Logic Flow: If delta_high > 0 then either SOF or BREAK
// if delta_low - 0x2B > 0 & delta_high > 0 then it is a break
// if delta_low - 0x2B <= 0 & delta_high > 0 then it is a SOF
// cases for delta_high == 0
// IF delta_low - 0xCC > 0 then it is a SOF
// If delta_low - 0x78 >= 0 & delta_low - 0xCC < 0 then it is a long pulse
// if delta_low - 0x2A >= 0 & delta_low - 0x78 < 0 then it is a short pulse
// if delta_low - 0x2A < 0 then it is too short procedure interrupt_handler is // edge has been detected on ccp1
pragma interrupt
tmr1_low_new = f877_ccpr1l
tmr1_high_new = f877_ccpr1h
// tmr1_new - tmr1_old = delta
assembler // 16-bit subtraction of old values from the new
btfss tmr1on
bsf tmr1on
bank MOVF tmr1_low_old,W
bank SUBWF tmr1_low_new,W
bank MOVWF delta_low
bank MOVF tmr1_high_old,W
BTFSS status_C
INCFSZ tmr1_high_old,W
bank SUBWF tmr1_high_new,W
bank MOVWF delta_high
end assembler
tmr1_low_old = tmr1_low_new // replace old values with new ones
tmr1_high_old = tmr1_high_new if ccp1m0 then // rising edge interrupt has been detected on ccp1
assembler
clrf f877_ccp1con // configure for falling edge
movlw falling
movwf f877_ccp1con
end assembler
else
// falling edge detected
assembler
clrf f877_ccp1con
movlw rising
movwf f877_ccp1con
end assembler
end if
pir1_ccp1if = false
pulse_rec = on
end procedure
OBDII Interface Project Source Code的更多相关文章
- Using command-line Subversion to access project source files
Help index About source code version control with Software Configuration Management (Subversion) Usi ...
- Tips for newbie to read source code
This post is first posted on my WeChat public account: GeekArtT Reading source code is always one bi ...
- Spring 4 MVC example with Maven - [Source Code Download]
In this tutorial, we show you a Spring 4 MVC example, using Maven build tool. Technologies used : Sp ...
- source code analyzer 功能强大的C/C++源代码分析软件 Celerity CRACK 破解版
特色 迅捷是一个功能强大的C/C++源代码分析软件.可以处理数百万行的源程序代码.支持标准及K&R风格的C/C++.对每一个打开的源代码工程,通过建立一个包含丰富交叉引用关系的数据库,显示其所 ...
- Indenting source code
Artistic Style 1.15.3 A Free , Fast and Small Automatic Formatterfor C , C++ , C# , Java Source Code ...
- How to build the Robotics Library from source code on Windows
The Robotics Library is an open source C++ library for robot kinematics, motion planning and control ...
- How to build windows azure PowerShell Source Code
Download any version source code of Windows Azure Powershell from https://github.com/Azure/azure-sdk ...
- 3 Ways of JDK Source Code Attachment in Eclipse---reference
You wanna look at a JVM class while you are coding and you cannot. Here is the solution. First of al ...
- Android Branch and master source code merge(patch)
Environment : Android 4.4.2 merge with Android 4.4.3(with other vendors source code) 1.确定你要merge 到 其 ...
随机推荐
- 【Android】ImageView ScaleType属性值
ImageView.ScaleType / android:scaleType值的意义区别: CENTER /center 按图片的原来size居中显示,当图片长/宽超过View的长/宽,则截取图片的 ...
- [转]Howto: 使用ImageBrush替换PictureMarkerSymbol以加强graphic显示性能
原文地址:http://support.esrichina-bj.cn/2009/0728/1007.html 文章编号 : 37033 软件: ArcGIS API for Microsoft Si ...
- JMeter上传案例2
今天自己的QQ群里有个朋友一直在问JMeter图片上传的问题 原始通过JMeter抓包如下: 参考: http://blog.csdn.net/huashao0602/article/details/ ...
- Flink应用开发-maven导入
flink和spark类似,也是一种一站式处理的框架:既可以进行批处理(DataSet),也可以进行实时处理(DataStream) 使用maven导入相关依赖 <properties> ...
- maven pom.xml(公司版)
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20 ...
- Python交互图表可视化Bokeh:1. 可视交互化原理| 基本设置
Bokeh pandas和matplotlib就可以直接出分析的图表了,最基本的出图方式.是面向数据分析过程中出图的工具:Seaborn相比matplotlib封装了一些对数据的组合和识别的功能:用S ...
- 040 Http与RPC
一直在说,但是没有系统的文档理解过. 1.本质 目前有很多Java的RPC框架,有基于Json的,有基于XML,也有基于二进制对象的. 他们最本质的区别,就是RPC主要是基于TCP/IP协议的,而HT ...
- java添加水印等比缩放
/** * 图片天加文字水印(默认缩小scale) * 备注: * Positions.BOTTOM_RIGHT 表示水印位置 * * @param filePath 原图路径 * @param ne ...
- Number String(DP)
题目: 题意: 给你一个字符串s,s[i] = 'D'表示排列中a[i] > a[i+1],s[i] = 'I'表示排列中a[i] < a[i+1]. 比如排列 {3, 1, 2, 7, ...
- POJ 3177 Redundant Paths (边双连通+缩点)
<题目链接> <转载于 >>> > 题目大意: 有n个牧场,Bessie 要从一个牧场到另一个牧场,要求至少要有2条独立的路可以走.现已有m条路,求至少要新 ...