社区首页
技术讨论创新帖
全部新帖
资料区
社区活动
联系管理员
★ 社区积分制度
★ 新手必读
★ 申请版主★
请
登录
后使用快捷导航
没有帐号?
注册
首页
|
电子技术
|
嵌入式
模拟电子
单片机
电源管理
传感器
半导体
电子应用
|
工业控制
物联网
汽车电子
网络通信
医疗电子
手机便携
测试测量
安防电子
家用电子
机器人
新能源
电子头条
|
社区
|
论坛
测评
博客
大学堂
|
下载
|
下载中心
电路图
精品文集
电路图
|
参考设计
|
Datasheet
|
活动
|
直播
datasheet
datasheet
文章
搜索
登录
注册
论坛
切换旧版
电子工程世界-论坛
»
论坛
›
专业技术中心
›
TI技术论坛
›
微控制器 MCU
›
MSP430的MODBUS实例
返回列表
发新帖
回复
阅
2065
|
回
0
fish001
当前离线
纯净的硅(中级)
最后登录
2023-10-7
在线时间
253 小时
威望
1125分
芯积分
830分
(兑换)
E金币
0枚
(兑换)
(兑换)
好友
0
fish001
3836
帖子
19
TA的资源
纯净的硅(中级)
+ 好友
私信
楼主
发表于2017-4-26 22:11
只看该作者
MSP430的MODBUS实例
[复制链接]
这是tsg9456原作者在实际应用中的源程序,希望能帮到大家,同样欢迎大家在微控论坛分享实用例程。
复制代码
#include "synth.h"
//------------------------------------------------------------------------------
bool CommState; // 通讯状态
bool Request; // 允许接收
bool Response; // 允许发送
bool EnCommWrite; // 允许通讯写
uchar UDRBuf; // 通讯接收寄存器缓存
uchar CommIndex; // 通讯索引
uchar CrcLow; // CRC低字节
uchar CrcHigh; // CRC高字节
uchar Interval; // 3.5字符时间间隔
uchar CommWrEntry; // 通讯写入口
uchar CommBuf[BUF_SIZE]; // 通讯缓冲区
uint StartAddr; // 起始地址
uint RegNum; // 寄存器数量
int bAudBuf; // 通讯波特率缓存
int FormBuf; // 通讯数据格式缓存
extern const StrKeybd Keybd[];
//------------------------------------------------------------------------------
void ResetInterval(void) // 重置3.5字符时间间隔
{
switch(bAudBuf)
{
case 0: Interval = (uchar)(1000/( 1200/11.0)*3.5/TBASE); break;
case 1: Interval = (uchar)(1000/( 2400/11.0)*3.5/TBASE); break;
case 2: Interval = (uchar)(1000/( 4800/11.0)*3.5/TBASE); break;
default: Interval = (uchar)(1000/( 9600/11.0)*3.5/TBASE); break;
case 4: Interval = (uchar)(1000/(19200/11.0)*3.5/TBASE); break;
}
}
//******************************************************************************
void OpenComm(void) // 打开或关闭通讯
{
ResetInterval();
UCA0CTL1 |= (UCSSEL_2 + UCRXEIE);
switch(FormBuf)
{
default: UCA0CTL0 = UCSPB; break; // N-2
case 1: UCA0CTL0 = UCPEN; break; // O-1
case 2: UCA0CTL0 = UCPEN + UCPAR; break; // E-1
case 3: UCA0CTL0 = 0; break; // N-1
}
switch(bAudBuf)
{
case 0: UCA0BR1 = (uint)(BRCLK/1200) >> 8;
UCA0BR0 = (uchar)((uint)(BRCLK/1200));
UCA0MCTL = (uint)((BRCLK/1200-(uint)(BRCLK/1200))*8)<<1;
break;
case 1: UCA0BR1 = (uint)(BRCLK/2400) >> 8;
UCA0BR0 = (uchar)((uint)(BRCLK/2400));
UCA0MCTL = (uint)((BRCLK/2400-(uint)(BRCLK/2400))*8)<<1;
break;
case 2: UCA0BR1 = (uint)(BRCLK/4800) >> 8;
UCA0BR0 = (uchar)((uint)(BRCLK/4800));
UCA0MCTL = (uint)((BRCLK/4800-(uint)(BRCLK/4800))*8)<<1;
break;
default: UCA0BR1 = (uint)(BRCLK/9600) >> 8;
UCA0BR0 = (uchar)((uint)(BRCLK/9600));
UCA0MCTL = (uint)((BRCLK/9600-(uint)(BRCLK/9600))*8)<<1;
break;
case 4: UCA0BR1 = (uint)(BRCLK/19200) >> 8;
UCA0BR0 = (uchar)((uint)(BRCLK/19200));
UCA0MCTL = (uint)((BRCLK/19200-(uint)(BRCLK/19200))*8)<<1;
break;
}
UCA0CTL1 &= ~UCSWRST;
IE2 |= UCA0RXIE;
}
//******************************************************************************
void Communication(void) // 通讯
{
if((SMM.out1 == COMM) || (SMM.out2 == COMM) || (SMM.out3 == COMM))
{
if((bAudBuf != SMM.bAud) || (FormBuf != SMM.ForM) || (!CommState))
{
bAudBuf = SMM.bAud;
FormBuf = SMM.ForM;
UCA0CTL1 = UCSWRST;
OpenComm();
CommState = true;
}
}
else
{
UCA0CTL1 = UCSWRST;
CommState = false;
}
}
//******************************************************************************
void SingleCRC(uchar data) // 计算单字节CRC校验码
{
uchar c = CrcLow ^ data;
CrcLow = TabCRC[c] ^ CrcHigh;
CrcHigh = TabCRC[c + 0x100];
}
//******************************************************************************
__monitor void SilentInterval(void) // 检测通讯3.5字符时间间隔
{
if(CommState)
{
if(Interval == 0)
{
ResetInterval();
CrcLow = 0xFF;
CrcHigh = 0xFF;
CommIndex = 0;
if(Response)
{
Response = false;
IE2 |= UCA0TXIE;
}
else
{
IE2 &= ~UCA0TXIE;
Request = true;
}
}
else
--Interval;
}
}
//******************************************************************************
bool CheckDataValid(void) // 检测写入数据的有效性
{
uchar c, index = StartAddr + OFFSET;
for(c = 0; c < RegNum; ++c, ++index)
{
uchar buf = c * 2;
int data = ((int)CommBuf[7 + buf] << 8) | CommBuf[8 + buf];
if((data < Keybd[index].LowerLimit) || (data > Keybd[index].HigherLimit))
return(false);
}
return(true);
}
//******************************************************************************
void GetDataToMenu(void) // 更新参数值
{
uchar c, *ta = &SB[(StartAddr + OFFSET) * 2], *src = &CommBuf[8];
for(c = RegNum; c; --c)
{ // 低字节
*ta = *src;
ta += 2; src += 2;
}
ta = &SB[(StartAddr + OFFSET) * 2 + 1], src = &CommBuf[7];
for(c = RegNum; c; --c)
{ // 高字节
*ta = *src;
ta += 2; src += 2;
}
}
//******************************************************************************
void GetDataToBuff(void) // 取参数值
{
uchar c, *ta = &CommBuf[4], *src = &SB[(StartAddr + OFFSET) * 2];
for(c = RegNum; c; --c)
{ // 低字节
*ta = *src;
ta += 2; src += 2;
}
ta = &CommBuf[3], src = &SB[(StartAddr + OFFSET) * 2 + 1];
for(c = RegNum; c; --c)
{ // 高字节
*ta = *src;
ta += 2; src += 2;
}
}
//******************************************************************************
void ManageWrite(void) // 写指令
{
uchar c = REGNUM * 2 + 7; // 指向CRCL
if(CommIndex < c)
{
SingleCRC(UDRBuf);
CommBuf[CommIndex++] = UDRBuf;
}
else if(CommIndex == c)
{
if(CrcLow == UDRBuf)
{
StartAddr = STARTADDR;
RegNum = REGNUM;
++CommIndex;
}
else
Request = false;
}
else
{
Request = false;
if(CrcHigh == UDRBuf)
{
if((RegNum >= 1) && (RegNum <= 0x7B) && (CommBuf[6] == (RegNum * 2)))
{
if((StartAddr + RegNum) <= COMM_WL_WR)
{
if(!CheckDataValid())
{
CMD |= 0x80; CommBuf[2] = ERR_DATA; // 非法数据
}
else
{
GetDataToMenu();
if(StartAddr < (COMM_WL_WR - 2))
{
switch(StartAddr+RegNum)
{
case COMM_WL_WR : RegNum -= 2; break;
case (COMM_WL_WR-1): RegNum -= 1; break;
default : break;
}
CommWrEntry = ENTRY;
EnCommWrite = true;
}
}
}
else
{
CMD |= 0x80; CommBuf[2] = ERR_ADDR; // 非法地址
}
}
else
{
CMD |= 0x80; CommBuf[2] = ERR_NUM; // 非法数量
}
Response = true;
}
}
}
//******************************************************************************
void ManageRead(void) // 读指令
{
if(CommIndex == 6)
{
if(CrcLow == UDRBuf)
{
StartAddr = STARTADDR;
RegNum = REGNUM;
CommBuf[2] = RegNum * 2;
++CommIndex;
}
else
Request = false;
}
else
{
Request = false;
if(CrcHigh == UDRBuf)
{
if((RegNum >= 1) && (RegNum <= 0x7D))
{
if((StartAddr + RegNum) <= COMM_WL_RD)
GetDataToBuff();
else
{
CMD |= 0x80; CommBuf[2] = ERR_ADDR; // 非法地址
}
}
else
{
CMD |= 0x80; CommBuf[2] = ERR_NUM; // 非法数量
}
Response = true;
}
}
}
//******************************************************************************
#pragma vector = USCIAB0TX_VECTOR
__interrupt void UART_transmit(void) // 通讯发送
{
uchar c;
TACCTL0 &= ~CCIE;
IE2 &= ~UCA0TXIE;
__enable_interrupt();
ResetInterval();
if(CMD == READ) // 读指令
c = CommBuf[2] + 3; // 指向CRCL
else if(CMD == WRITE) // 写指令
c = 6;
else // 错误的指令
c = 3;
if(CommIndex <= (c + 1))
{
if(CommIndex < c)
{
c = CommBuf[CommIndex];
SingleCRC(c);
UCA0TXBUF = c;
}
else if(CommIndex == c)
UCA0TXBUF = CrcLow;
else
UCA0TXBUF = CrcHigh;
++CommIndex;
__disable_interrupt();
IE2 |= UCA0TXIE;
TACCTL0 |= CCIE;
}
else
{
__disable_interrupt();
TACCTL0 |= CCIE;
}
}
//******************************************************************************
#pragma vector = USCIAB0RX_VECTOR
__interrupt void UART_receive(void) // 通讯接收
{
UDRBuf = UCA0RXBUF;
TACCTL0 &= ~CCIE;
IE2 &= ~UCA0RXIE;
__enable_interrupt();
ResetInterval();
if(Request)
{
switch(CommIndex)
{
case 0: if(UDRBuf != SMM.Addr)
{
Request = false;
break;
}
case 1:
case 2:
case 3:
case 4:
case 5: SingleCRC(UDRBuf);
CommBuf[CommIndex++] = UDRBuf;
break;
default: if(CMD == READ) // 读指令
ManageRead();
else if(CMD == WRITE) // 写指令
ManageWrite();
else // 非法指令
{
Request = false;
CMD |= 0x80; CommBuf[2] = ERR_CMD;
Response = true;
}
break;
}
}
__disable_interrupt();
IE2 |= UCA0RXIE;
TACCTL0 |= CCIE;
}
此帖出自
微控制器 MCU论坛
点赞
关注
(1)
TI MCU论坛
TI MSP430论坛
MSP430技术讨论
回复
分享
扫一扫,分享给好友
复制链接分享
链接复制成功,分享给好友
举报
提升卡
变色卡
千斤顶
返回列表
发新帖
回复
您需要登录后才可以回帖
登录
|
注册
发表回复
回帖后跳转到最后一页
活动
更多>>
有奖直播报名中!抢占工业4.1先机,WT·世健科技日等你来!
罗姆有奖直播 | 重点解析双极型晶体管的实用选型方法和使用方法
STM32N6终于要发布了,ST首款带有NPU的MCU到底怎么样,欢迎小伙们来STM32全球线上峰会寻找答案!
免费下载 | 安森美电动汽车充电白皮书,看碳化硅如何缓解“里程焦虑”!
是德科技有奖直播 | 应对未来高速算力芯片的设计与测试挑战
TI 有奖直播 | 使用基于 Arm 的 AM6xA 处理器设计智能化楼宇
安世半导体理想二极管与负载开关,保障物联网应用的稳健高效运行
报名直播赢【双肩包、京东卡、水杯】| 高可靠性IGBT的新选择——安世半导体650V IGBT
开源项目
更多>>
LTC3723EGN-1 隔离式推挽式转换器的典型应用电路
使用 Microchip Technology 的 LM285EOA-2.5 的参考设计
LTC8043 的典型应用 - SO-8 中的串行 12 位乘法 DAC
EVAL-ADM1066TQEB,评估 ADM1066ASU 电压监控器排序器的评估板
USB一体化扬声器
LTC1734,针对 300mA 输出电流编程的简单、低成本充电器
使用 MaxLinear, Inc 的 AS1117 的参考设计
多模网关
LTC3610、12A 单片式同步降压稳压器接受高达 24V 的输入
具有 12VDC 和 24VAC 辅助输入的 LT4275AIMS 25W PD 解决方案的典型应用电路
随便看看
分享基于MSP430的MODBUS实例
这是tsg9456原作者在实际应用中的源程序,希望能帮到大家运行代码复制代码#include"synth.h"//------------------------------------------------------------------------------boolCommState;//通讯状态boolRequest;//允许接收boolResponse;//允许发送b ...
MSP430WARE++的使用3:modbus模块的调用方法
[color=#333333][font=punctuation,微软雅黑,Tohoma][font=楷体,楷体_GB2312][size=18px]MSP430WARE是一套基于C++语言的开源的MSP430层次化软件架构,支持多种外设。本文将介绍modbus模块驱动程序的调用方法。[/size][/font][font=楷体,楷体_GB2312][size=18p ...
打开BOSS一看,推一大堆深圳的职位
今晚闲着无事,无意间打开BOSS直聘看了一下。明明选了广州的,但是BOSS推荐的广州职位基本上都很鸡肋,反而推送了不少深圳地区的职位过来。难道说广州的电子产业已经快要消亡了?还是说单纯只是年末了,所以招人的公司少。但是,不管怎么说,想要跳槽而且想找 ...
delphi 多格式图像显示
两位595驱动8位共阴极数码管的程序问题
降压升压电池充电器如何改变您的设备充电方式
msp430 IO中断问题
重金求购 Tornado V 2.2.1的序列号(现金)
MSP430F22X学习套件硬件仿真问题
杯具啊,我的F429的板子也收到了,但LCD屏排线断了有8根
查找数据手册?
搜索
EEWorld Datasheet 技术支持
热门标签
源代码
单片机
放大器
TI
ST
电源
分立器件
传感器
测试测量
模拟
接地导通测试仪
直接变频电路
防水连接器
继电器触点
函数发生器
按键电路
OpenTitan
流媒体
LDO电路
TLP250
相关文章
更多>>
欧洲三大芯片巨头,重新审视供应链
在上周刚刚举办的Electronica 2024 CEO圆桌论坛上,英飞凌,恩智浦以及意法半导体三家芯片巨头CEO齐亮相,三家CEO集体表达了对中美关系的担忧,同时三位也有一个共识,即中国在全球半导
消息称铠侠最快明天获上市批准,市值有望达 7500 亿日元
11 月 21 日消息,路透社报道称,在贝恩资本的支持下,铠侠将于当地时间周五(11 月 22 日)获东京证券交易所上市批准。 根据其 IPO 指示价,铠侠的市值预计达到约 7500 亿日元(当前约
美国政府敲定对格芯 15 亿美元《CHIPS》法案补贴,支持后者提升在美产能
11 月 21 日消息,美国商务部当地时间昨日正式宣布将向格芯 GlobalFoundries 提供合计 15 亿美元(当前约 108.71 亿元人民币)的《CHIPS》法案直接资金,具体补贴发放将
SK 海力士宣布量产全球最高的 321 层 1Tb TLC 4D NAND 闪存,计划 2025 上半年对外出货
UWB上车新花样,无线BMS也能用它?
填补国内空白!中国移动、华为等联合发布首颗GSE DPU芯片
三星电子 NRD-K 半导体研发综合体进机,将导入 ASML High NA EUV 光刻设备
苹果揭秘自研芯片成功原因:竞争对手没法用最新尖端技术
芯片大混战将启:高通、联发科涉足笔记本,AMD 被曝入局手机
Exynos 2600 芯片成关键,消息称三星将打响 2nm 芯片反击战
新帖速递
STM32和无源蜂鸣器播放声音的问题
车规级AECQ200介绍,混合铝电解电容器的选择
嵌入式教程_DSP技术_DSP实验箱操作教程:2-28 搭建轻量级WEB服务器实验
OPA847IDBVR运放器国产替代
AG32VF407测试UART
【得捷电子Follow Me第二期】第一章 收到货物的分享
请问这个红外接收头是什么型号?能用哪个型号代替?谢谢
出售全新未拆封ZYNQ 7Z020 FPGA核心板
用在锂电池供电的水表设置上的LORA模块,当有100块水表集中安装在一个楼道内时,节能
请问一下,当某个端口被设置为 RX0后,这个端口的输入输出方向还有必要设置吗
今年怎么这么难,比疫情时还难,三十了面临失业好迷茫
请教稳压管测试问题
【小华HC32F448测评】关于小华半导体的UART中断发送和PRINTF构造和重定向
【BIGTREETECH PI开发板】 HDMI输出测试
【BIGTREETECH PI开发板】+08.音频测试(zmj)
精选推荐
【2024 DigiKey创意大赛】 超声波感测矩阵 小结
CW32L010学习笔记
帮忙分析下EMI不过的原因
报名剩2天:30套RV1106 Linux开发板(带摄像头),邀您挑战边缘AI~
拯救电源EMI的铁三角:电感、磁珠、电容
开关电源上拉电阻和上拉电阻电路图解
启明云端&触觉智能与您相约2024年慕尼黑国际电子元器件博览会,不见不散!
深度学习框架的相关讨论
[STM32H7R/S]测评 ⑦制作一个NANO EDGE AI STUDIO采集数据使用的Data Logger
启明云端&触觉智能与您相约2024年慕尼黑国际电子元器件博览会,不见不散!
等待很久的STM32N6终于要发布了!
ST首款带有NPU的MCU到底怎么样,欢迎小伙们来STM32全球线上峰会寻找答案!报名峰会,还能赢【开发板、京东卡】呦~12月12日14:00不见不散!
查看 »
有奖直播报名| 高可靠性IGBT新选择 —— 安世半导体650V IGBT
【直播时间】12月19日(周四)下午15:00-16:30
【直播好礼】定制双肩商务包、30元京东卡、吸管玻璃杯
查看 »
安世半导体直播报名中
直播主题:安世半导体理想二极管与负载开关,保障物联网应用的稳健高效运行
直播时间:12月17日(周二)下午14:00
报名就有机会获得:定制双肩商务包、30元京东卡、吸管玻璃杯
查看 »
PI 电源小课堂 | 无 DC-DC 变换实现多路高精度输出反激电源
时间:即日起-12月15日
看视频学习电源干货,答题赢取京东卡!
查看 »
参会有好礼 | 2024 瑞萨电子MCU/MPU工业技术研讨会
深圳站:11月30日(周六)深圳湾万怡酒店
上海站:12月06日(周五)上海喜玛拉雅酒店
奖励设置:现金红包、螺丝刀套装或30元京东卡
查看 »
Littelfuse 新品赋能电子产品安全可靠并高效, 10+挑战等你探索!
Littelfuse 应用赋能星球,覆盖了诸多应用痛点及解决办法,邀请工程师一起探索,解锁更多设计力!
查看 »
下载资料赢好礼!看Vicor模块化电源解决方案如何推动创新
活动时间:即日起-2024年12月31日
如何参与:点击活动页内您想了解的模块,找到资料下载即可参与抽奖,活动结束后统一发奖!
查看 »
有奖活动|英飞凌高密度双相电源模块为高性能运算平台而生
活动时间:即日起-12月15日
活动奖励:蓝牙音箱、氮化镓充电器套装、黑色小背包
查看 »
本月精选下载推荐:
Vishay——选型-汽车级表面贴装和通孔超快整流器
查看 »
本周精选下载推荐:电源管理基础Dummies
本周小编给大家带来一本超简单、超干货的电子书——《电源管理基础Dummies》!内容深入浅出,排版舒服简洁,分分钟能get到电源管理最核心的知识内容。
查看 »
关闭
站长推荐
1
/10
电子工程世界版权所有
京B2-20211791
京ICP备10001474号-1
电信业务审批[2006]字第258号函
京公网安备 11010802033920号
Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复
返回顶部
返回列表
论坛首页
版块列表
专业技术中心
TI技术论坛
ST传感器与低功耗无线技术论坛
ADI参考电路
DigiKey得捷技术专区
ADI · 世健工业技术
电子技术交流
嵌入式系统
单片机
国产芯片交流
电机驱动控制
FPGA/CPLD
模拟电子
电源技术
PCB技术
RF/无线
传感器
综合技术交流
下载中心专版
大学堂专版
测评中心专版
创意与实践
电子竞赛
DIY/开源硬件专区
淘e淘
创意市集
行业应用
汽车电子
移动便携
医疗电子
工控电子
安防电子
休息一下
聊聊、笑笑、闹闹
工作这点儿事
为我们提意见&公告
EEWorld颁奖专区
信息发布
最新帖子
最新帖子
最新回复
精华
消灭零回复
测评中心
活动中心
积分兑换
E金币兑换
芯积分
厂商专区
TI技术论坛
ST传感器与低功耗无线技术论坛