64位WINDOWS 7下的WINDOWS XP虚拟机(因为win7下jtag没驱动,这驱动困扰了我好长时间,还因为装双系统失败而重装系统,资料都没了。最终用Vmware Workstation解决)。
采用AVR128单片机,C语言编写程序,avrstudio4setup.exe4.19 + WinAVR-20100110-install.exe + vr-toolchain编辑、编译、仿真。
所需器材:
1.USB接口JTAG仿真器+AVR128单片机(用jtag连接电脑后将后文中的C程序代码通过avrstudio4这个软件烧写进单片机的CPU中,至于avrstudio4的使用说明网上有很多,这里不再说明):
2.SRD-5VDC-SL-C 1路 5V继电器驱动模块 :
3.TCP232-T 串口转以太网双向以太网转串口TCP,IP转串口、RJ45转TTL。
4.智能手机一部
5.电灯....
1、系统设计:
1.AVR128 PORTD,操作继电器模块(后文有开发板和继电器的原理图,及连接方式)
2.AVR128 Usart0与TCP232-T通讯,接收指令转换PORTD电平
3.继电器模块,实现火线通断控制,进一部控制电器设备,本例控制电灯
4.TCP232-T模块,实现串行通讯与TCP通讯的通明传输。工作模式为Client,TCP协议,主动连接远程服务器。接收AVR128的指令,
智能手机,通过WEB网页或者应用软件控制远程电灯
2、指令协议(由遥控端发送到服务器,再由服务器广播到TCP232-T模块,再由单片机进行接下来的控制继电器部分,最后达到控制电灯的目的)
1.开灯指令:1212140400DBBF PORTD输出低电平,继电器模块获得低电位,常开状态转换为闭合状态
2.关灯指令:12121404FF9BFF PORTD输出低电平,继电器模块获得低电位,常开状态转换为闭合状态
3.查询灯状态指令:12121404AAxxxx获取PORTD状态并返回。
其中12121404为本例标识。TCP232-T模块成功连接服务端后,发送设备设备标识。本例为12121404,控制指令以12121404起头。
十六进制
发送1212140400DBBF
其中12121404为标识,00为开灯指令,DBBF为CRC检验码(用来检验控制端发送的16进制代码和服务器端收到的16进制代码是否相同,详见后文的C程序代码)
控制器返回[123.4.244.144:20108] 45
其中123.4.244.144为控制器IP地址,20108为控制器TCP端口,45表示指令格式正确,并被正确执行
控制器返回[123.4.244.144:20108] 4BDBBF
4BDBBF表示指令标识正确,但是CRC不正确,正确的CRC为DBBF
控制器返回[123.4.244.144:20108] 4B
非指令或者其他错误。
3、智能家居物联网控制器功能设计
电源,采用220转5V/200mA统一供电,其他部件由单片机提供VDD5V和VCC3.3V,单片机工作在5V状态(注意跳线)。
其中TCP232-T需要50mA才能稳定工作,SRD-5VDC-SL-C也需要50mA才能正确动作。所以采用独立电源。
共地设计。
花絮:实验过程中,使用计算机USB(2.0)供电,单独编程实验继电器能能正常动作,单独使用TCP232-T也能正常连接网络。联合调试的时候,继电器不动作。分析原因,起初以为单片机提供电流有限,负载能力差,后来考虑到单片机本身需要100mA左右电流,随采用独立电源供电,以提供更大电流。实验成功。
AVR单片机开发板
有两供电方,USB和独立电源,并有5V和3.3跳线。本例单片机工作在5V状态。
使用5V供电,3个接线柱,分别为电源正,控制线(低电位有效),电源地。分别连接到电源正,AVR的PORTD口,电源地。
继电器模块输出(连接被控制设备,本例为电灯电源线中的火线),有3个接口,中间为公共地,一端为常开状态,另一端为常闭状态。本例使用常开状态,接收用户指令,实现常开和闭和动作。
电源使用5V供电,串行通讯为TTL电平(<3.3V为0,3.5-5V为1。串口为-9V - +9V电平,〈0V为0,〉1V为1。两种接口不能接错),TTL电平可以直接接单片机端口。
如果是TTL电平,直接POARTE0和POARTE1,如果是串口模块,接单片机开发板串口。串口只使用2,3,5三根线。
4、原理图
AVR开发板
PORTD接继电器模块,为简单,写端口0x00或者0xFF,以控制端口电平,实现控制继电器动作。
PORTE接8个LED,一般用来在开发过程中指示工作状态,本例最终版本无用。
POARTE0和POARTE1接TTL电平的TCP232-T模块的TXD和RXD
POARTE0和POARTE1另外设计连接MAX232转换芯片和接口,供串口设备通讯。
USART1接485转换口
另有电源总开关、复位键和4个键盘。
输入端,分别接电源正,PORTD任意一个,和电源地
输出端,使用常开接口,只能控制1条线路。其他空置悬空。
电源,电源正接VDD,电源地接GND。
?RJ45接口,标准的网口,使用1、2、3、6四根线
?串口端,TTL电平,RXD接POARTE0,POARTE1接TXD
?电源,电源正接VDD,电源地接GND。
?CFG空置,如果被拉底,比如接GND,则模块工作于串口设置模式,不响应网络连接。
?复位,接PORTF,复位通讯模块。
5、使用说明
服务器:
本软件使用VB编写
Modbus协议规定的传输媒介有串行总线和以太网两种,其中串行总线规定了ASCII模式和RTU模式两种传输方式。本软件以GB/T19582-2008为蓝本,实现Modbus协议的TCP模式、ASCII模式和RTU模式之间相互转换;并将UDP协议纳入TCP模式,实现广播通讯;模拟应答,没有物理设备也可以调试系统。扩展了TCP模式,开发出微型Webserver,实现了3种模式与HTTP协议之间的转换,使通用浏览器(比如Window的IE或者Andriod的浏览器)成为控制器。
RJ45,网口
J1,控制线,23公共,1为常开,4为常闭。可以控制250V以下电压,2A电流。
电源,5V
开关,总电源开关
本例使用RJ45口网络配置,专用软件。工作于Client模式,通过有线内部网络,连接公网SERVER。根据网络环境,设置静态IP,不支持DHCP。
可设置本机IP,网关,端口20108,和远程SERVER地址和端口8234。心跳设计,断网自动连接。
智能手机TCP应用软件模式:
用于局域网和广域网,本例为安卓应用软件
网上找到有个叫easytcp的软件比较好使,可以配合SERVER使用
智能手机WEB模式(不太稳定):
用于广域网,本例为通用浏览器,支持HTML即可。HTTP协议,端口9000。
6、程序设计
这里给出核心代码
//*************************************************************************
//继电器模块编程设计
//*************************************************************************
#define Lamp_IOPORTD//继电器模块所在数据口
#define Lamp_DDRDDRD//方向寄存器
Lamp_IO=0xFF;//数据口为输出
Lamp_DDR=0xFF;
if((data_buf[RX_length-1]==0xFF) ||(data_buf[RX_length-1]==0x00))
{
usart_send(0x45);//将接收到的数据再发出去
Lamp_Display(data_buf[RX_length-1]);//写PORTD,控制继电器模块,继电器低电平有效,0xFF为关灯,0x00为开灯
}
//*************************************************************************
//USART通讯设计
//*************************************************************************
//由于采用通明传输,因此本例只涉及USART通讯编程,使用USART0,也就是PORTE0和PORTE1。
//初始化
#define baud9600//设置波特率的大小
#define baud_setting(uint)((ulong)F_CPU/(16*(ulong)baud)-1)//波特率计算公式
#define baud_h(uchar)(baud_setting>>8)//提取高位
#define baud_l(uchar)(baud_setting)//低位
void usart_init()
{
UCSR0A=0x00;//单倍速模式
UCSR0B=0xF8;//接收中断和发送中断允许
UCSR0C=(1<
UBRR0H=baud_h;//写波特率的值
UBRR0L=baud_l;
}
//发送数据
void usart_send(uchar data)
{
while( !( UCSR0A & (1<
UDR0 = data; //接收到的数据再发回电脑
delay_ms(2);
}
//数据接收结束中断向量
SIGNAL(SIG_USART0_RECV)//中断服务程序
{
uchar RxTemp;
RxTemp=UDR0;//将接收到的数据取出
usart_rx_data[RxReadIndex]=RxTemp;
if(++RxReadIndex> Rx_Buf_Size)//如果写接收缓冲区索引大于接收缓冲区的长度
RxReadIndex=0;//则索引重新清0
rx_flag=1;
}
//*************************************************************************
//CRC检验和判断
//*************************************************************************
uint get_crc(uint n)
{
uchar i,j;
CRC_word=0xffff;//赋值:0xffff
for(i=0;i
{
CRC_word^=(uint)data_buf[i];//计算CRC_word
for(j=0;j<8;j++)
{
if(CRC_word&0x0001)
{
CRC_word=CRC_word>>1;
CRC_word^=0xa001;
}
else
{
CRC_word>>=1;
}
}
}
return CRC_word;
}
判断
RX_length=RxReadIndex-2;//*256+data_buf[3];//取数据长度数据
RX_CRC_word=data_buf[RX_length+1]*256+data_buf[RX_length];//取CRC校验码
CRC_word=get_crc(RX_length);//计算接收数据校验码
if(CRC_word==RX_CRC_word)//校验数据比较
{}
两位CRC码提取
(CRC_word%256);
(CRC_word/256);
//*************************************************************************
//主程序
//*************************************************************************
int main(void)
{
system_init();//系统初始化
usart_init();//usart串口初始化配置
SREG|=0x80;//开启全局中断
while(1)
{
_delay_ms(50);//为串口中断方式延迟,这个很重要,本例通讯数据少,因此设置50
if((RxReadIndex>0) && (rx_flag==1))
{
cli();//全局中断无效,同SREG=0x00;
RX_data=&usart_rx_data[0];//指针接收数组首地址
for(read_count=0;read_count
{
data_buf[read_count]=*RX_data++;
usart_send(data_buf[read_count]);
}
receive_code_fun();
_delay_us(5);
RxReadIndex=0;//接收中断次数清零
rx_flag=0;
sei();//开全局中断,同SREG|=0x80;
}
}
}
server采用VB设计
使用控件,创建微WEB服务器,接受并解析HTTP协议,执行指令后返回HTML数据流。
指令只转发给受控制端。
主页源代码如下:
===========================
MODBUS调试---上海大学陈歌MODBUS协议转换助手
ID
地址
数据
读开关量
02
读寄存器
04
这里显示的是,返回数据
普通数据发送
16进制
字符串
==================================