|
/****************************************************** {# G1 c& |4 \: J$ _ modbus-rtu 通讯规约7 C, c7 c5 E: ~2 |: S# R 通讯方式:rs-485 半双功# L/ L% z. y; M 校验方式:crc16 停止位:2位5 \& I; g) T9 R; F* E$ Y5 K5 F 编写:孙可+ H5 R. u. ]2 q0 n5 ^ 编程思路:- G/ [2 T8 e% M2 F 1.串口中断允许自动接收总线上的信息,当接收的字节后超过3.5个字节时间没有新的字节认为本次接收完成,接收完成标志置1;如果接收完成标志已经置1又有数据进来则丢弃新来的数据。 2.串口接收数据的处理, 当接收完成标志置1进入接收数据处理, (1)首先判断接收的第一位数据与本机地址是否相同,如果不相同清空接收缓存不发送任何信息; (2)接收的第一位数据与本机地址相同,则对接收缓存中的数据进行crc16校验,如果接收的校验位与本校验结果不相同清空接收缓存不发送任何信息;(3)如果crc16校验正确则根据数据串中的命令码进行相应的处理。" s6 f5 q) }5 S8 |, T) `" M$ M0 J ******************************************************/- _- I0 i( V" [4 E' _* ?% j4 { / Z- x& h- v. o% q. I #include "modbus.h" u8 Com0_id = 0x05;//本机串口0的通讯地址: }% T- Q/ G; V+ ]4 M u8 Uart0_rev_buff[100];//com0串口接收缓冲区! x" J; [2 Z! V7 l' ^ u8 Uart0_send_buff[100];//com0串口发送缓冲区+ c6 A% K- A" l9 g vu8 Uart0_rev_count; vs8 Uart0_send_counter = 0; vu8 Uart0_rev_comflag; vu8 Crc_counter = 0;//com0校验计数器 vu8 *Uart0_send_pointer = Uart0_send_buff;//com0串口发送指针; M0 m+ V5 K: e+ y' {( u0 m vu16 Mkgz_bz = 0;//模块故障标志1:输入异常,2:过压,3:欠压,4:过温 vu16 Out_current = 50;//输出电流2 h4 w7 x- M" P, H2 F6 _0 Q vu16 Out_voltage = 240;//输出电压 vu16 Mkzt_bz = 0;//模块状态标志 vu16 OutX_current = 1000;//输出限流! \% O$ O, w+ c# C% u& S! U vu16 Jc_voltage = 2530;//均充电压! _6 m' Y5 P) I+ U5 o& F0 T vu16 Fc_voltage = 2400;//浮充电压- q: Q, v7 M( B7 x0 i& j vu16 user_day = 1825;//使用天数 void Delay(vu32 nCount);2 Y: _* @9 f' M2 b0 b unsigned short getCRC16(volatile unsigned char *ptr,unsigned char len) ; void mov_data(u8 a[100],u8 b[100],u8 c);/ H" C6 W3 ^% `$ J& q void Modbus_Function_3(void); void Modbus_Function_6(void); " W8 l0 n& V0 f/ ]0 [ /**************************************** @& Y6 @1 X+ V. G 函数名称:crc16校验3 I" r4 f2 n2 V* a% e6 A% J, T" G 函数功能:crc16校验 函数输入:字节指针*ptr,数据长度len 函数返回:双字节crc 函数编写:孙可 编写日期:2008年6月9日' C" f3 k/ s7 y 函数版本:v0.2+ u( {! q4 [1 @ ****************************************/ unsigned short getCRC16(volatile unsigned char *ptr,unsigned char len) + U$ w7 R: o* d { unsigned char i; unsigned short crc = 0xFFFF; ' v1 L' l7 E! ^/ i: ], b Y9 l if(len==0) { len = 1; } while(len--) { crc ^= *ptr; - K5 c' F/ F' q8 h for(i=0; i>= 1; crc ^= 0xA001; & h$ W6 m4 |# i/ @% F } else { crc >>= 1; } } 3 ]2 b7 T; {7 H" Y) Z) i ptr++; 4 o [8 e; p9 K0 S2 I } return(crc); } /***************************************: o- [" E5 M. Y8 M9 ^ 块数据复制数据函数 功能:把数组a的c个数据复制到数组b中% B" d/ g5 b* X4 {, V 输入:指针a,指针b,数据个数c 返回:无2 a& ~3 J+ M' _; b8 ^ 编写:孙可 编写日期:2008年3月28日 版本:v0.1 ****************************************/ void mov_data(u8 a[100],u8 b[100],u8 c) { u8 i; for(i=c; i>0; i--)! \6 j# Q1 N. X9 Y { a = b;& v# h; L5 j) K$ e& E# \ } } /////////////////////////////////////////////////////////////////////// void Modbus_Function_3(void) ' V3 j+ M( X r& L { % H$ N! a1 F% E: S7 c5 u- O7 c u16 tempdress = 0;' h0 n" b% Z5 k5 h& F7 R4 s u8 i = 3; u16 crcresult; tempdress = (Uart0_rev_buff[2] = 0x0120) & (tempdress + Uart0_rev_buff[5] < 0x0132)) {/ R! Q- G2 j: Y: D: L, J6 C" a) j Uart0_send_buff[0] = Com0_id;) x, t: B' I q' ]7 { Uart0_send_buff[1] = 0x03; Uart0_send_buff[2] = 2 * Uart0_rev_buff[5]; " h9 c3 P. {* C) c Uart0_send_counter = 2 * Uart0_rev_buff[5] + 3;2 O) Y; l$ x( m switch(tempdress) { case 0x0120: { Uart0_send_buff = Mkgz_bz & 0xff; i++;3 ?' u E7 G4 Y$ x* v Uart0_send_buff = (Mkgz_bz >> 8) & 0xff;/ w3 i+ _7 W6 j6 ?2 o0 m) n i++; }//后面不放break的目的是继续往下执行& B5 A8 J7 |& G! j) v+ c$ X case 0x0122: _" x. A y8 a7 C/ e' @; [ {; I; N( Q, E1 [, R& I* H T, b# R% } Uart0_send_buff = Out_voltage & 0xff; i++; Uart0_send_buff = (Out_voltage >> 8) & 0xff; i++; " s! |, |9 H) }$ t! L9 E }) W f; K- J1 m2 s case 0x0124: { Uart0_send_buff = Out_current & 0xff;1 W. X3 G" S2 k8 I i++; Uart0_send_buff = (Out_current >> 8) & 0xff; i++; 9 D& x3 y- @+ p+ H }2 ?: H: _1 g$ n/ N) ^/ t0 t: y+ t case 0x0126:& a1 L6 b) L3 k# w% L {' D! W# F8 |! {7 e; d Uart0_send_buff = Mkzt_bz & 0xff; i++; Uart0_send_buff = (Mkzt_bz >> 8) & 0xff;9 C/ p! [9 T% r4 `5 a d4 _) {& H i++; ' \4 _3 g( S2 c' N }& P& V* N2 `/ I1 a9 f case 0x0128://这个地址是备用的里面的数据没有意义+ P& Z$ D0 C4 f! l {- V* P& }& r$ h/ h Uart0_send_buff = 0x00;& o3 U5 L( e8 M. \. l+ h i++; Uart0_send_buff = 0x00;8 y4 C+ F8 A5 X- f' d& [! x i++; } case 0x012A:* D; v( J! J9 L) u) j( h2 V { Uart0_send_buff = OutX_current & 0xff;* w. ?. ~7 j; n# T8 X9 T/ P/ O2 J8 o i++; O( M `" O+ F Y5 ^' K Uart0_send_buff = (OutX_current >> 8) & 0xff; i++;& w! C2 D6 u8 D6 f }4 W0 R5 C0 M( v$ A$ ] case 0x012C:5 K. @5 D0 K) e9 J/ e { Uart0_send_buff = Jc_voltage & 0xff; i++;9 i) i- a5 h, f, t4 T2 }9 V; N7 s, L Uart0_send_buff = (Jc_voltage >> 8) & 0xff;( W( u/ `( {5 h8 d/ ] i++;! U& t4 b/ ~) H' v1 n( g% H U } case 0x012E:( q2 f) j3 U5 M j { Uart0_send_buff = Fc_voltage & 0xff; i++; Uart0_send_buff = (Fc_voltage >> 8) & 0xff;0 q9 k0 z% P o i++; } case 0x0130:: h! z+ G3 h# D6 v4 ~' A, K {6 k4 f7 B! ~! |, ^* i5 M Uart0_send_buff = 0x00;# S- B/ Y; _* y" @3 _' U" A5 j i++; Uart0_send_buff = 0x00;, d) s! W/ |# v" B8 N i++;. I# v1 ?! c3 Z9 c } } , M" V, n6 T7 D* C. ^ O8 R$ J* ^ //UCSRB |= (1 |
STM32L562DK探索板——串口通讯测试成功
OpenBLT移植到STM32F103战舰开发板上适用于所有STM32F103系列的Bootloader
NUCLEO-H723ZG开发板试用 ——串口点灯测试
MultiButton移植到STM32F103战舰开发板
汇编浮点库qfplib移植STM32F769I-DISCO开发板与硬件浮点运算性能测试对比
【STM32MP157】从ST官方例程中分析RPMsg-TTY/SDB核间通信的使用方法
S2LP 的 sniff 模式如何同时满足通讯和低功耗要求
双证齐发!移远通信通过ISO 26262功能安全流程认证及产品认证
意法半导体 STHV200超声波 IC单片简化设计
了解NFC技术优势与应用场景
微信公众号
手机版
RE:STM32F的232口简易MODBUS-RTU通讯程序
RE:STM32F的232口简易MODBUS-RTU通讯程序
RE:STM32F的232口简易MODBUS-RTU通讯程序
RE:STM32F的232口简易MODBUS-RTU通讯程序
回复:STM32F的232口简易MODBUS-RTU通讯程序
为方便沟通,特此留下QQ1024829053
RE:STM32F的232口简易MODBUS-RTU通讯程序
{
u8 i;) a6 G7 B- D9 ], f. c
for(i=c; i>0; i--)) u5 \: t: @0 w K- V2 s ^8 e
{ G6 T, A0 V$ g& X p) v4 b4 C. a
a = b;
}
}. M' L6 C! }3 B/ y
+ p, Y! z* M0 S; s
这个函数有问题吧? a、b分别是数组名称,能直接用a=b吗?