RTX实时平台实现RS232通讯
2012-07-04 22:34
197 查看
关键词 RTSS Win32 UART NI SharedMemory
在工控领域,特别是我比较熟悉的半导体行业,设备与设备之间的通讯一般有TTL, RS232, GPIB, RJ45等,RS232是其中常见的且运用广泛的一种通讯方式。因其简单易用,在设备之间短距离通讯,一般都采用RS232。
简单介绍一下RS232:
根据引脚数量分为 DB9(9个引脚,比较常见,PC都是用这个)和DB25(25个引脚),我就不介绍了,具体的介绍网上搜一下,一大摞。
通讯连接方式分为: 1)无握手方式, 2)全握手方式, 3)循环握手回送方式。
本文主要介绍RS232通讯在RTX平台下运用,方便起见,我采用无握手方式来介绍。
(关于全握手方式请参考河北工业大学葛磊蛟等写的”基于C语言的RS232串行接口通信实现”。)
我这边就只用到3个引脚:发送数据(TXD), 接收数据(RXD)和信号地(GND).
接线:发送接接收,接收接发送,地线接地线。
在同一台电脑上通过把发送端和接收端短接,我给出的示例也是这么做的。
硬件配置参数主要是:
1. 端口 COM1, COM2,COM3 选择不同的IO地址。
2. 波特率Baud Rate,单位时间内载波调制状态改变次数。
3. 数据长度 Data Length, 传输字符的数据位。
4. 停止位,表示一个字符的结束。
5. 奇偶校验位,校验数据位是否受到干扰而产生错误,但只能针对某一位产生错误,多位就不行了。
一般设定9600, 8, 1, N.
什么是RTX实时平台
如上图所示,一般Windows程序都是在用户模式下运行的,即Win32 Subsystem(Ring 3).而RTX可以直接与HAL硬件链路层沟通,是在内核模式下运行的(Ring 0),称为Real-time Subsytem。
显而易见,RTX构架的程序不会受Windows其他程序的干扰,且直接与硬件沟通可以获得硬件的直接反馈,实现它的实时性。
关于RTX的特点介绍看我另外一篇博客:
“RTX解决方案-给那些在windows操作系统下需要对时间进行精准控制且需要提高运行速度的应用”
下面切入正题:RTX实时平台实现RS232通讯
1. 准备动作
a. 安装RTX
首先要试用RTX平台,可以从IntervalZero(前身Ardence)官方网站上下载试用版的程序或者在CSDN上下载试用版
RTX8.1 Demo part1/2
RTX8.1 Demo part2/2
安装后,打开RTX属性,检查如下驱动是否都启动。
b. 配置VC++ 6.0(RTX 8.1版)
打开IDE, Tools -> Options->Directories, 选择Win32, Include files。Directories添加:C:/Program Files/Ardence/RTX/include, Library files下面添加C/Program
Files/Ardence/RTX/lib和C:/Program Files/Ardence/RTX/lib/VisualStudio6.
其他版本看帮助文件。
2.基本构架
3.如何避开Win32 subsystem, 直接与UART对话
第一步,在控制面板,打开【RTX属性】
第二步,选择【hardware】,【Devices】下点击【Settings】
第三步,选择硬件COM1,2…, 点击右键,选择【Add RTX INF Support】,点击【Apply】
第四步,然后在设备管理器上更新COM端口的驱动,不要使用自动选择,必须手动选择RTX Support Driver.
这样通讯端口就被添加在RTX下面,可以直接与UART对话。
4.开始构建程序
a. 创建和打开SharedMemory
在Win32界面上创建一个SharedMemory用来与RTSS沟通
[cpp]
view plaincopyprint?
RtCreateSharedMemory((DWORD)PAGE_READWRITE,
(DWORD)0,
(DWORD)(sizeof(SHAREDMEMORY)), //大小为创建的结构体size
sharedmemory,
&location)
pSHM = (pSHAREDMEMORY)location; //并指向该结构体
b. 通讯端口初始化
我们用9600, 8, 1, N来初始化通讯端口
i) 找到该端口的IO首地址: COM1:0x038f
ii) 参考NI UART PC16550D芯片 Datasheet
[cpp]
view plaincopyprint?
RtWritePortUshort((PUSHORT)(com_port+INTERRUPT_ENABLE), 0);
//'暂停接收数据中断
//设置 DLAB = 1 divisor latch access bit,这样可以进入baud generator的除法器
//设置DLAB = 0 才能进入Receiver Buffer
RtWritePortUshort((PUSHORT)(com_port+LINE_CONTROL), (USHORT)(RtReadPortUshort((PUSHORT)(com_port + LINE_CONTROL)) | DLAB));
//设置波特率
baud_rate = MAXBAUDRATE / baud_rate;
RtWritePortUshort((PUSHORT)(com_port+BAUD_RATE_LO), (USHORT)baud_rate);
//使能 FIFO模式
RtWritePortUshort((PUSHORT)(com_port+FIFO_CONTROL), (USHORT)(FIFO_ENABLE + 0x80));
//设置数据长度,停止位,奇偶校验,并设置DLAB=0可以准备开始接收和读取数据
RtWritePortUshort((PUSHORT)(com_port+LINE_CONTROL), (USHORT)(data_length + stop_bit + parity_bit));
//恢复UART中断
RtWritePortUshort((PUSHORT)(com_port+ INTERRUPT_ENABLE), (USHORT)ivalue);
//确认端口的状态,如overrun/parity/framing错误
RtReadPortUshort((PUSHORT)(com_port + LINE_STATUS)) & 0x1e)
//0001 1110
//设置 DTR打开(数据终端准备)
RtWritePortUshort((PUSHORT)(com_port+MODEM_CONTROL), (USHORT)(RtReadPortUshort((PUSHORT)(com_port + MODEM_CONTROL))|0x01));
//设置 RTS 打开(请求发送)
RtWritePortUshort((PUSHORT)(com_port+MODEM_CONTROL), (USHORT)(RtReadPortUshort((PUSHORT)(com_port + MODEM_CONTROL))|0x02));
d. 运行线程
[cpp]
view plaincopyprint?
DWORD Send_Data(LPVOID lpvThreadParm)
{
while(1)
{
if((TXD_CHECK == ON)&&(psm->bSent == TRUE)) //可以进行数据传输
{
RtWritePortBufferUchar((PUCHAR)iPort, (PUCHAR)psm->sentBuffer, strlen(psm->sentBuffer)); //把字符串批量读入到缓存里
psm->bSent = FALSE;
bActive = TRUE; //告诉接收线程可以接收
}
RtSleep(20);
}
}
关于Win32下如何进行RS232通讯,我就不说了,自己看源代码吧。
Hongxin
hongxin.he#gmail.com
2010-5-18
附: 演示代码界面
源代码下载地址:http://download.csdn.net/source/2368302
文献来源:/article/8854811.html
查看评论
6楼 yjukh
2012-02-07 16:42发表
[回复] [引用]
[举报]
在工控领域,特别是我比较熟悉的半导体行业,设备与设备之间的通讯一般有TTL, RS232, GPIB, RJ45等,RS232是其中常见的且运用广泛的一种通讯方式。因其简单易用,在设备之间短距离通讯,一般都采用RS232。
简单介绍一下RS232:
根据引脚数量分为 DB9(9个引脚,比较常见,PC都是用这个)和DB25(25个引脚),我就不介绍了,具体的介绍网上搜一下,一大摞。
通讯连接方式分为: 1)无握手方式, 2)全握手方式, 3)循环握手回送方式。
本文主要介绍RS232通讯在RTX平台下运用,方便起见,我采用无握手方式来介绍。
(关于全握手方式请参考河北工业大学葛磊蛟等写的”基于C语言的RS232串行接口通信实现”。)
我这边就只用到3个引脚:发送数据(TXD), 接收数据(RXD)和信号地(GND).
接线:发送接接收,接收接发送,地线接地线。
在同一台电脑上通过把发送端和接收端短接,我给出的示例也是这么做的。
硬件配置参数主要是:
1. 端口 COM1, COM2,COM3 选择不同的IO地址。
2. 波特率Baud Rate,单位时间内载波调制状态改变次数。
3. 数据长度 Data Length, 传输字符的数据位。
4. 停止位,表示一个字符的结束。
5. 奇偶校验位,校验数据位是否受到干扰而产生错误,但只能针对某一位产生错误,多位就不行了。
一般设定9600, 8, 1, N.
什么是RTX实时平台
如上图所示,一般Windows程序都是在用户模式下运行的,即Win32 Subsystem(Ring 3).而RTX可以直接与HAL硬件链路层沟通,是在内核模式下运行的(Ring 0),称为Real-time Subsytem。
显而易见,RTX构架的程序不会受Windows其他程序的干扰,且直接与硬件沟通可以获得硬件的直接反馈,实现它的实时性。
关于RTX的特点介绍看我另外一篇博客:
“RTX解决方案-给那些在windows操作系统下需要对时间进行精准控制且需要提高运行速度的应用”
下面切入正题:RTX实时平台实现RS232通讯
1. 准备动作
a. 安装RTX
首先要试用RTX平台,可以从IntervalZero(前身Ardence)官方网站上下载试用版的程序或者在CSDN上下载试用版
RTX8.1 Demo part1/2
RTX8.1 Demo part2/2
安装后,打开RTX属性,检查如下驱动是否都启动。
b. 配置VC++ 6.0(RTX 8.1版)
打开IDE, Tools -> Options->Directories, 选择Win32, Include files。Directories添加:C:/Program Files/Ardence/RTX/include, Library files下面添加C/Program
Files/Ardence/RTX/lib和C:/Program Files/Ardence/RTX/lib/VisualStudio6.
其他版本看帮助文件。
2.基本构架
3.如何避开Win32 subsystem, 直接与UART对话
第一步,在控制面板,打开【RTX属性】
第二步,选择【hardware】,【Devices】下点击【Settings】
第三步,选择硬件COM1,2…, 点击右键,选择【Add RTX INF Support】,点击【Apply】
第四步,然后在设备管理器上更新COM端口的驱动,不要使用自动选择,必须手动选择RTX Support Driver.
这样通讯端口就被添加在RTX下面,可以直接与UART对话。
4.开始构建程序
a. 创建和打开SharedMemory
在Win32界面上创建一个SharedMemory用来与RTSS沟通
[cpp]
view plaincopyprint?
RtCreateSharedMemory((DWORD)PAGE_READWRITE,
(DWORD)0,
(DWORD)(sizeof(SHAREDMEMORY)), //大小为创建的结构体size
sharedmemory,
&location)
pSHM = (pSHAREDMEMORY)location; //并指向该结构体
在RTSS下,打开该SharedMemory [cpp] view plaincopyprint? hsm = RtOpenSharedMemory(SHM_MAP_WRITE, FALSE, argv[0], &psm)) == NULL) //打开SharedMemory hsm = RtOpenSharedMemory(SHM_MAP_WRITE, FALSE, argv[0], &psm)) == NULL) //打开SharedMemory
b. 通讯端口初始化
我们用9600, 8, 1, N来初始化通讯端口
i) 找到该端口的IO首地址: COM1:0x038f
ii) 参考NI UART PC16550D芯片 Datasheet
[cpp]
view plaincopyprint?
RtWritePortUshort((PUSHORT)(com_port+INTERRUPT_ENABLE), 0);
//'暂停接收数据中断
//设置 DLAB = 1 divisor latch access bit,这样可以进入baud generator的除法器
//设置DLAB = 0 才能进入Receiver Buffer
RtWritePortUshort((PUSHORT)(com_port+LINE_CONTROL), (USHORT)(RtReadPortUshort((PUSHORT)(com_port + LINE_CONTROL)) | DLAB));
//设置波特率
baud_rate = MAXBAUDRATE / baud_rate;
RtWritePortUshort((PUSHORT)(com_port+BAUD_RATE_LO), (USHORT)baud_rate);
//使能 FIFO模式
RtWritePortUshort((PUSHORT)(com_port+FIFO_CONTROL), (USHORT)(FIFO_ENABLE + 0x80));
//设置数据长度,停止位,奇偶校验,并设置DLAB=0可以准备开始接收和读取数据
RtWritePortUshort((PUSHORT)(com_port+LINE_CONTROL), (USHORT)(data_length + stop_bit + parity_bit));
//恢复UART中断
RtWritePortUshort((PUSHORT)(com_port+ INTERRUPT_ENABLE), (USHORT)ivalue);
//确认端口的状态,如overrun/parity/framing错误
RtReadPortUshort((PUSHORT)(com_port + LINE_STATUS)) & 0x1e)
//0001 1110
//设置 DTR打开(数据终端准备)
RtWritePortUshort((PUSHORT)(com_port+MODEM_CONTROL), (USHORT)(RtReadPortUshort((PUSHORT)(com_port + MODEM_CONTROL))|0x01));
//设置 RTS 打开(请求发送)
RtWritePortUshort((PUSHORT)(com_port+MODEM_CONTROL), (USHORT)(RtReadPortUshort((PUSHORT)(com_port + MODEM_CONTROL))|0x02));
c. 创建收发线程 [cpp] view plaincopyprint? hSendThread= CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Send_Data, NULL, 0, &dwSendThreadID); hReceiveThread=CreateThread(NULL,0, (LPTHREAD_START_ROUTINE)Receive_Data, NULL, 0, &dwReceiveThreadID); hSendThread= CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Send_Data, NULL, 0, &dwSendThreadID); hReceiveThread=CreateThread(NULL,0, (LPTHREAD_START_ROUTINE)Receive_Data, NULL, 0, &dwReceiveThreadID);
d. 运行线程
[cpp]
view plaincopyprint?
DWORD Send_Data(LPVOID lpvThreadParm)
{
while(1)
{
if((TXD_CHECK == ON)&&(psm->bSent == TRUE)) //可以进行数据传输
{
RtWritePortBufferUchar((PUCHAR)iPort, (PUCHAR)psm->sentBuffer, strlen(psm->sentBuffer)); //把字符串批量读入到缓存里
psm->bSent = FALSE;
bActive = TRUE; //告诉接收线程可以接收
}
RtSleep(20);
}
}
[cpp] view plaincopyprint? DWORD Receive_Data(LPVOID lpvThreadParm) { … while(1) { if((RXD_CHECK == ON)&&(bActive == TRUE)) //缓存有数据 { RtSleep(20); //等待字符串批量写入完毕 for(i=0;i<sizeof(psm->receivedBuffer);i++) //针对不定长数据 { timeout=5; while((RXD_CHECK==OFF)&&(timeout-- > 0)) RtSleep(1); if(timeout <= 0x00) { psm->receivedBuffer[i]=0x00; break; } else psm->receivedBuffer[i] = RtReadPortUchar((PUCHAR)iPort); } } RtSleep(20); } } DWORD Receive_Data(LPVOID lpvThreadParm) { … while(1) { if((RXD_CHECK == ON)&&(bActive == TRUE)) //缓存有数据 { RtSleep(20); //等待字符串批量写入完毕 for(i=0;i<sizeof(psm->receivedBuffer);i++) //针对不定长数据 { timeout=5; while((RXD_CHECK==OFF)&&(timeout-- > 0)) RtSleep(1); if(timeout <= 0x00) { psm->receivedBuffer[i]=0x00; break; } else psm->receivedBuffer[i] = RtReadPortUchar((PUCHAR)iPort); } } RtSleep(20); } }
关于Win32下如何进行RS232通讯,我就不说了,自己看源代码吧。
Hongxin
hongxin.he#gmail.com
2010-5-18
附: 演示代码界面
源代码下载地址:http://download.csdn.net/source/2368302
文献来源:/article/8854811.html
查看评论
6楼 yjukh
2012-02-07 16:42发表
[回复] [引用]
[举报]
相关文章推荐
- RTX实时平台实现RS232通讯
- elk实时日志分析平台部署搭建详细实现过程
- elk实时日志分析平台部署搭建详细实现过程:加上个人实践意见,及如何避坑
- Android平台Camera实时滤镜实现方法探讨(三)--通过Shader实现YUV转换RBG
- Android平台Camera实时滤镜实现方法探讨(十一)--实时美颜滤镜
- elk实时日志分析平台部署搭建详细实现过程
- 【实时计算架构系列1】WePay如何基于谷歌云平台(GCP)和kafka实现实时流式欺诈检测
- elk实时日志分析平台部署搭建详细实现过程
- ELK实时日志分析平台部署搭建详细实现过程
- RTX实时平台介绍(2) – 说说Sleep(1)
- 用cpld实现嵌入式平台上的实时图像增强
- 使用Mkfifo和Script命令实现在Linux平台上实时演示
- TiDB 帮助万达网络科技集团实现高性能高质量的实时风控平台
- Android平台Camera实时滤镜实现方法探讨(八)--滤镜基本制作方法(二)简单美颜滤镜
- 开源分布式搜索平台ELK(Elasticsearch+Logstash+Kibana)+Redis+Syslog-ng实现日志实时搜索
- [置顶] 自定义Hbasesink实现自定义rowkey及实时传输数据库数据至大数据平台
- 开源分布式搜索平台ELK+Redis+Syslog-ng实现日志实时搜索
- Android平台Camera实时滤镜实现方法探讨(三)--通过Shader实现YUV转换RBG
- RTX企业实时通信平台二次开发
- Android平台Camera实时滤镜实现方法探讨(一)--JNI操作Bitmap