单片机的freemodbus移植应用

前一段时间一直在研究modbus协议的源代码,并且自己用单片机C实现了一下但是其实没什么卵用的,因为根本就不可能用在实际工程中也是自己当时太不懂行情了上网搜了一下我觉得实际人家产品上用的很少应该是自己去写,因为那根本就不合算而且还会出错,又走了弯路我觉得一般的做从站用freemodbus就很好也是因为水平太菜就这个freemodbus也差不多弄了有1个礼拜今天终于搞定了能转起来并能正确的返回数据因此在这里总结一下:
1、使用的单片机是stm32 F103来做移植,裸机移植没有加操作系统(后边在uCOS上移植好了在补充)
2、协议栈是我从官网上下的最新的1.6
一开始我是想移植网上流传的一个周立功公司的协议栈但是我弄了两天觉得太难了因为首先那只是一个文档说的其实也不是很清楚而且要自己移植的部分差别太大。我是把串口部分和定时器部分都移植好了之后发现在主调函数中的eMBPoll()中是靠一个事件来询问的,但是那个事件怎么初始化、GET、POST我都没弄明白所以 我就放弃了主要是他那个说是不仅可以做从栈还支持主站模式因为他那里很巧妙的还每次检查1.5T的时间,还有一个就是我当时不清楚怎么在没有操作系统的状态下进入临界区的没弄明白就放弃了。
就下了一个freemodbus来看了一下网上资料也很多就好多了。源代码我就不说了但是我建议一定要先看懂最重要的是两个文件mb.c和mbrtu.c这两个文件一定要看懂。还有就是在mbport.h中已经给你声明好了你需要自己动手编写的文件,照着那个思路来就可以了。编译的时候要注意最好是把那个MicroLib的勾去掉不然会报错,如果还是想用printf()来调试的话也可以用一个隐式的声明网上很多我就不写了我随便找了一个就可以用。在有就是ENTER_CRITICAL_SECTION()和EXIT_CRITICAL_SECTION()我在网上搜了一下我觉得有两种方法一种是用ARM汇编一种是用标准库里也有两个对应的关总中断和开总中断的函数我看了一下没记住我用的ARM汇编的那种如下
void
EnterCriticalSection( )
{
__ASM volatile("cpsid i");
}

void
ExitCriticalSection( )
{
__ASM volatile("cpsie i");
}
把关键的代码贴出来我觉得把这几项弄清楚应该就没什么问题了:
void main(void)

{
NVIC_Configuration();

eMBInit(MB_RTU, 1, 0, 9600, MB_PAR_NONE);

eMBEnable();
while(1)
{
 (void)eMBPoll();
}

}
主函数这套了就比较套路了在官网上就是这么给的也没什么说的。下面我就按照协议的调用流程来贴出来了
串口初始化函数:
void uart_init(u32 bound)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);

//USART1_RX   PA.10
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);  

USART_InitStructure.USART_BaudRate = bound;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; 

USART_Init(USART1, &USART_InitStructure);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
USART_Cmd(USART1, ENABLE);                   

}
这个也比较常规了
事件初始化函数
static eMBEventType eQueuedEvent;
static BOOL xEventInQueue;

BOOL
xMBPortEventInit( void )
{
xEventInQueue = FALSE;
return TRUE;
}
时间初始化函数
BOOL
xMBPortTimersInit( USHORT usTim1Timerout50us )
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

TIM_TimeBaseStructure.TIM_Period = 50;
TIM_TimeBaseStructure.TIM_Prescaler = (7200 - 1);
TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

TIM_Cmd(TIM2, ENABLE);
return TRUE;

}
还有两个时间的函数也比较简单
void
vMBPortTimersEnable( )
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
TIM_SetCounter(TIM2, 0);
//TIM_Cmd(TIM2, ENABLE);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
}

void
vMBPortTimersDisable( )
{
TIM_SetCounter(TIM2, 0);
//TIM_Cmd(TIM2, DISABLE);
TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE);
}
把串口中断和时钟中断的函数也贴出来
void USART1_IRQHandler(void)
{
//static unsigned int u;
//u++;

    if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
{
    prvvUARTRxISR();
    USART_ClearITPendingBit(USART1, USART_IT_RXNE);
    //printf("u=%u\r\n",u);
}
    if(USART_GetITStatus(USART1, USART_IT_TXE) == SET)
{

    //printf("com in ittxe intrupt\r\n");
    prvvUARTTxReadyISR();
    //USART_ClearITPendingBit(USART1, USART_IT_TC);
}

}
void TIM2_IRQHandler(void)
{
//static unsigned int t;
//t++;
//printf("t=%u",t);
TIMERExpiredISR();
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);

}
还有就是事件的请求和发送函数
BOOL
xMBPortEventPost( eMBEventType eEvent )
{
xEventInQueue = TRUE;
eQueuedEvent = eEvent;
return TRUE;
}

BOOL
xMBPortEventGet( eMBEventType * eEvent )
{
BOOL xEventHappened = FALSE;

if( xEventInQueue )
{
    *eEvent = eQueuedEvent;
    xEventInQueue = FALSE;
    xEventHappened = TRUE;
}
return xEventHappened;

}
这样应该就没什么大问题了,仔细点,在多分析协议源码多花点时间就肯定没有什么问题解决不了。****

原文地址:http://blog.51cto.com/13638458/2308626

时间: 2024-08-30 07:38:27

单片机的freemodbus移植应用的相关文章

【HAL库每天一例】freemodbus移植

例程下载:资料包括程序.相关说明资料以及软件使用截图 百度云盘:https://pan.baidu.com/s/1slN8rIt 密码:u6m1 360云盘:https://yunpan.cn/OcPiRp3wEcA92u密码 cfb6 (硬石YS-F1Pro开发板HAL库例程持续更新\6. 软件设计之Modbus(HAL库版本)\YSF1_HAL_freemodbus_001. freemodbus移植)/**  ****************************************

单片机脚本语言-移植lua到stm32-MDK

Lua简介 Lua[1]  是一个小巧的脚本语言.作者是巴西人.该语言的设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能. Lua脚本可以很容易的被C/C++ 代码调用,也可以反过来调用C/C++的函数,这使得Lua在应用程序中可以被广泛应用.不仅仅作为扩展脚本,也可以作为普通的配置文件,代替XML,Ini等文件格式,并且更容易理解和维护. Lua的目标是成为一个很容易嵌入其它语言中使用的语言.大多数程序员也认为它的确做到了这一点. 很多应用程序使用LUA作为自己的嵌入式脚本

freemodbus移植讲解

一   为什么要移植Freemodbus 为什么要移植Freemodbus,这个问题需要从两个方面来回答.第一,modbus是一个非常好的应用层协议,它很简洁也相对完善.对于还没有接触过modbus的朋友来说,我非常不建议直接移植freemodbus,应该耐心的从modbus文档入手,并充分把握身边的所有资源,例如PLC的中modbus部分.第二,其实嵌入式系统的通信协议可以自己制定,但是通过实践发现自己定制的协议漏洞百出,尤其是扩展极为困难.我始终认为借鉴他人的经验是很好的途径.借鉴他人成熟的

以软件推动工业进步 -嵌入式学习网站

http://www.cnblogs.com/cubean/archive/2010/04/26/1721035.html 以下内容转自:http://bbs.msembed.com/showtopic-1238.aspx 嵌入式入门篇:什么是嵌入式系统                        http://www.helloarm.com/Embedded-Learn/58.htm嵌 入式资深工程师白话说“嵌入式”        http://www.helloarm.com/Embed

学习ARM+Linux的很好的资料(转)

前段时间做了一个关于ARM9 2440资料的汇总帖,很高兴看到***和CSDN等论坛朋友们的支持和鼓励.当年学单片机的时候datasheet和学习资料基本都是在论坛上找到的,也遇到很多好心的高手朋友,耐心的回答我提出的问题.感激.图报,很简单的想法.希望这次整理的资料帖能对更多的嵌入式爱好者朋友带来帮助! PS:    在此特别感谢 古道热肠 版主把我的帖子加精,给小弟极大鼓舞! 嵌入式入门篇: 什么是嵌入式系统                         http://www.helloa

uCOS-II的嵌入式串口通信模块设计

在嵌入式应用中,使用RTOS的主要原因是为了提高系统的可靠性,其次是提高开发效率.缩短开发周期.uCOS-II是一个占先式实时多任务内核,使用对 象是嵌入式系统,对源代码适当裁减,很容易移植到8~32位不同框架的微处理器上.但uCOS-II仅是一个实时内核,它不像其他实时操作系统(如嵌入式 Linux)那样提供给用户一些API函数接口.在uCOS-II实时内核下,对外设的访问接口没有统一完善,有很多工作需要用户自己去完成.串口通信是 单片机测控系统的重要组成部分,异步串行口是一个比较简单又很具代

学习韦东山视频心得(三)

学习韦东山视频心得(三) I2C总线广泛的用于各种传感器中,仅仅通过SDA,SCL线实现了主机与设备之间的通信.Linux系统中I2C驱动较为庞大.Linux系统中可以采用两种方式实现I2C设备驱动,我们既可以把I2C设备当做普通的字符设备去操作,同时可以利用内核中庞大而错综复杂的框架.如果当做普通的字符设备,程序员只要把管脚模拟时序或者I2C控制器自己实现不采用内核框架,使得程序员不需去研究I2C设备驱动庞大的框架,但是,如此写出来的驱动移植性跟单片机相差无几,移植性能很差,优点是比较直截了当

(转载)uCOS-II的嵌入式串口通信模块设计

在嵌入式应用中,使用RTOS的主要原因是为了提高系统的可靠性,其次是提高开发效率.缩短开发周期.uCOS-II是一个占先式实时多任务内核,使用对象是嵌入式系统,对源代码适当裁减,很容易移植到8~32位不同框架的微处理器上.但uCOS-II仅是一个实时内核,它不像其他实时操作系统(如嵌入式Linux)那样提供给用户一些API函数接口.在uCOS-II实时内核下,对外设的访问接口没有统一完善,有很多工作需要用户自己去完成.串口通信是单片机测控系统的重要组成部分,异步串行口是一个比较简单又很具代表性的

7-STM32物联网开发WIFI+GPRS基础篇(STM32+Wi-Fi(AT指令)实现MQTT远程通信控制)

https://www.cnblogs.com/yangfengwu/p/10840517.html 新板子终于到了,耽搁时间了,抱歉哈!为了表达歉意,我做了几套代码提供给大家 这节的代码也作为整版测试 看名字就知道了,简单的说 就是  单片机使用AT指令控制模块实现MQTT通信控制 先看这节 STM32+WIFI(AT指令)实现MQTT通信控制: 一,下载STM32程序 1,方式一,串口下载(其他下载方式在最后补充) ①调整拨动开关位置 → 短接BOOT0和3.3V → 复位STM32 ②打开