tag 标签: stm32

相关帖子
相关博文
  • 热度 1
    2021-7-9 21:10
    62 次阅读|
    0 个评论
    FreeModbus从站设计(12)-Modbus的通信参数存在flash中,如果改乱了,该怎么办 关键词:FreeModbus 复位默认参数 HAL库 flash STM32 在上一篇文章中,介绍了如何将Modbus的通信参数存储在单片机STM32F103C8T6的flash中,这样可以简化硬件电路设计,功能扩展也更加灵活。但孔丙火(微信公众号:孔丙火)认为,这种方法也有副作用,因为是用通信的方法修改参数,如果用户把上次修改的参数忘记了,岂不是无法建立串口连接了?要么一个一个参数地试,费时费力,要么重新刷单片机的程序,但这需要开发工程师的参与。公众号之前有一篇文章,是讲PLC的上电停止功能的,这里可以做一个借鉴,来解决这个问题。大体的意思,就是为用户保留一个数据命令,当单片机上电的时候,收到这个命令,就采用默认的通信参数运行,这时用户是可以通过串口连接单片机的,然后再把通信参数改成自己需要的就可以了。 下面来讲一下具体方法。 (1)设置默认通信参数,孔丙火(微信公众号:孔丙火)这里称之为“复位默认参数”,就是说单片机复位后,每次都是按照这个参数来运行Modbus,经过一定的时间后,再切换到用户设定的参数。 如图1所示,在程序的初始化阶段,先设置默认通信参数,这里设为:从站地址为1,波特率19200bps,偶校验,停止位1位。 (2)用定时器做一个定时,定时500ms(这个根据自己的实际情况来定),在这个时间内如果收到按默认参数运行的数据指令,则不切换通信参数,否则切换到用户设定的Modbus参数。 如图2所示,在回调函数eMBRegHoldingCB()中,这个函数在之前的章节中讲过的,当收到写保持寄存器命令后,先对相应的数组进行处理,然后判断ucUsrInitBaud这个变量,这个变量的初始化值为0定时500ms后再定时器的中断中将其置位1,在500ms以内,如果收到按默认参数运行的数据指令,则响应,过了500ms,则不响应这个指令。 图1 图2 如果从站地址为1,从地址0开始写寄存器的数量为2,分别为0xff55,和0xaaff,则一直按默认参数运行Modbus。也就是说,如果收到主站发来的数据为:01 10 00 00 00 02 04 FF 55 AA FF ED 4B,则一直按默认参数运行Modbus。用变量ucUsrTurnonStop来标记。 (3)切换用户设定的Modbus参数。如图3所示,在定时器溢出中断回调函数中,在第一次500ms定时时间到时,对ucUsrComReset变量赋值,为0xff表示一直按默认参数运行Modbus,为0x55表示切换用户设定的Modbus参数。 图3 如图4所示,在程序主循环中,如果ucUsrComReset==0x55,则先停止停止协议栈,然后重新进行初始化,并将ucUsrComReset置为0xff,保证只进行一次重新初始化。 图4 孔丙火(微信公众号:孔丙火)这里展示的是我的实现方法,主要是讲思路,朋友们也可以有自己的实现逻辑和方法,而且我这个方法并不是最好的。 至此,就实现了上电500ms内按照“复位默认参数”运行Modbus,然后根据主站传输来的数据,判断下一步怎么运行。如果需要按“复位默认参数”运行,则需要在500ms内,向从站发送:01 10 00 00 00 02 04 FF 55 AA FF ED 4B。通常的做法是:在单片机上电前,不停的向其发送这个数据,然后再给单片机上电。 如果用户忘记了之前修改的Modbus通信参数,则可以在“复位默认参数”状态,按照上一节讲的在线修改通信参数的方法,改成自己需要的参数,然后再把单片机重启就可以正常的通信了。 文章在公众号( 孔丙火 )同步推出,欢迎查看更多系列文章。 单片机、ARM、现场总线、PLC、嵌入式软硬件的设计经验分享,秉承“点点滴滴皆智慧”的理念,以实际项目为单元阐述知识点,一起分享,共同交流。
  • 热度 3
    2021-1-18 14:16
    953 次阅读|
    1 个评论
    作者:良知犹存 转载授权以及围观:欢迎添加微信公众号:羽林君 前言 主题 :串口是一种设备间常用的通讯接口,rosserial将串口字符数据转发到标准ROS网络,并输出到rosout和其日志文件。本文将记录如何在ROS上使用其提供的serial包进行串口通信。 我的环境介绍 : PC:使用的是Ubuntu 16-04 ROS-Kinetic 嵌入式端:STM32F071 ROS机器人操作系统是用于创建机器人系统的功能强大的平台,其中包括开发项目所需的一切,从最简单的软件组件(称为“节点”)和数据交换协议到真正的凉亭机器人平台的仿真环境。至于ROS这个操作系统的介绍大家可以看我之前的那篇文章《 嵌入式为什么要学ROS 》 总之ROS是一个在机器人设备端比较常用的分布式处理框架,但是因为ROS的包很多功能也比较复杂,所以一般都是跑在linux系统的板卡上,像stm32一类的单片机就使用的比较少,但是如果我们想用ROS的通讯接口到我们STM32中,那我们应该怎么做呢? 使用介绍 这个时候就要提起rosserial,这个ROS提供一种嵌入式节点和运行在主控PC上的ros master通信的方式,使得在嵌入式节点上编写、运行ros节点成为可能,主要用于转接IO和各类传感器,运行底层控制算法。 要使用rosserial,显然需要分别在嵌入式板卡和主控PC上部署,当前支持的板卡有: arduino stm32等这些比较热门的嵌入式端。 但是目前关于结合STM32微控制器使用ROS机器人操作系统的信息,其实网上使用的还是很少,不过网上还是有几个比较好的的stm32结合ROS使用的代码,其中有一个stm32rc和rtt的配置,不过RTT的配置我使用之后发现有些问题,已经给RTT在github的仓库提交了问题 不过RT_Thread官网的文档中心还是做的很好的,对于使用ROSSERIAL的包在STM32还是介绍的很详细,大家有兴趣可以去看一下 https://www.rt-thread.org/document/site/tutorial/smart-car/ros-connect/ros-connect/ ROSLib实战的使用 首先stm32 ROS serial的使用分为两部分,分别为PC端ROS环境接收数据, 嵌入式端STM32进行发送ROS数据。 首先我是使用的其他人分享一个包进行开发的,使用的是makefile文件进行编译,编译器选择的是 gcc-arm-none-eabi-4_9-2015q3 程序文件如下所示: 其中Bsp包里面主要是stm32串口串口配置的文件和时间定时的程序文件: 在这里插入图片描述 这里的配置方法其实就和我们平时的用库函数配置STM32串口的方法没什么区别,只不过是配置程序放到了HardwareSerial这个类成员函数中。 Dirver包中是我进行自定义的各种电机控制和IMU等的程序包 从程序文件的名称大家应该就可以看出来,这个部分的文件也是做外设等的基本配置,数据的基本发送和接收部分。例如:这里面wheel的配置 lib目录下有两个lib库: 其中 rsolib 其实就是使用ROS的时候程序中需要的头文件,ros msg的各种类。 这些类是我们定义ROS的topic或者service节点时候发送的数据类型,以及ROS serial的串口配置等头文件都在这个包里面 stm32lib 是stm32配置时候的各种库文件,包括stm32f0xx.h、CMSIS、库文件和启动汇编文件 再下面src目录里面就放着我们的 main.cpp 这个部分是比较重要的,main函数的部分除了初始化,我们也可以定义我们需要的topic节点。 initialise(); ros::NodeHandlenh; nh.initNode() while (!nh.connected()){ //nh.loginfo( "rosisnotconnect\r\n" ); nh.spinOnce(); } sensor_msgs::ChannelFloat32VelFeedBack; ros::Publishervelfeedbackpub( "VelFb_" ,&VelFeedBack); nh.advertise(velfeedbackpub); nh.spinOnce(); float fbVel ; while (1) { if =(1000/DEBUG_RATE))//定时发送 { VelFeedBack.name= "r" ; VelFeedBack.values=fbVel; VelFeedBack.values_length=7; velfeedbackpub.publish(&VelFeedBack); } nh.spinOnce(); } 最后面是部分是 makfile 文件,其中makefile文件分了两部分,一个include头文件,一个makefile文件。 makefile.include 文件中,和正常的IDE选项一样,里面包含了芯片选择、编译选择、链接选择、以及相应的程序文件目录设置。 其中芯片我选择了STM32F072 编译选项我按照默认,也没有修改,其中交叉编译器是用的 arm-none-eabi-gxx makefile 文件中我设置了我自行定义的程序文件 此外我还下载了 arm-none-eabi-gxx 的包 编译前先用export 配置一个编译器的选项: 其中我下载好的编译器目录在 /home/lyn/M0/gcc-arm-none-eabi-4_9-2015q3 export PATH=/usr/ local /sbin:/usr/ local /bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/home/lyn/M0/gcc-arm-none-eabi-4_9-2015q3/bin 使用 make 命令 编译,最后会在当前目录生成一个main.bin文件,这个时候我们就可以把main.bin文件通过j-link或者st-link下载软件把程序下载到板子中去。 PC端连接 PC端安装ROS大家可以参考我之前的 ROS安装的文章 ,一般安装ROS都是安装的全功能版本(全功能含有ROSSERIAL),如果你只是安装了部分的话,那你还需要多进行安装ROS serial sudo apt-get install ros-kinetic-rosserial-python 我是使用我们最常见的USB转串口工具连接到我的电脑端口。 在这里插入图片描述 我们首先检查串口号 用命令 “ls /dev/ttyUSB*” 一定要在程序中USB的参数完全一致。 首先在一个终端开启 roscore 然后使用我们安装好的 rosserial_python 进行启动节点 rosrunrosserial_pythonserial_node.py/dev/ttyUSB0_baud=115200 当然第一次启动会进行报错,权限不够,拒绝访问,,此时我们就需要对USB的权限进行设置,使得 /dev/ttyUSB0 可以被读写 sudochmod777/dev/ttyUSB0 在启动过程中,我们就可以看到我们设置的publis的 VelFb_就初始化了。 此时我们使用 rostopic list 就可以看到相应注册好的通信点,然后再使用 rostopic echo /VelFb_ 结语 这就是我使用STM32接入ROS节点的方法,大家有什么更好的建议可以一起和我交流,如果大家对代码感兴趣,可以在 公众号后台回复我 STM32使用ROSLIB 或者 微信私我 。我把我使用的代码和编译器一个分享给感兴趣的朋友们。
  • 热度 6
    2021-1-15 21:49
    5873 次阅读|
    5 个评论
    【ART-Pi开发板】+RT-Thread Studio实现快速开发
    众所周知,RTT是国产RTOS中佼佼者,不光光是因为其OS本身,还是因为其构建了良好的开发生态环境。包括丰富的中间件,友好的版本控制体系,以及自主开发的IDE—— RT-Thread Studio 。那么今天我们就利用RT-Thread Studio迅速搭建了个flashLEDdemo。 当然,首先你得安装RT-Thread Studio,这就不赘述了,附上下载链接: https://www.rt-thread.org/page/download.html 。双击打开IDE,点击SDK manager,我们要找到我们这块板卡的SDK以及H7的内核库文件,看下,ART-Pi的SDK是依赖于H7内核库的,如果之前没有安装H7库文件的话,IDE会提示先安装,安装完了再去安装基于ART-Pi的SDK即可。 库文件都安装完毕以后我们就可以新建项目了。点击文件——新建——RT-Thread项目。弹出对话框后,先输入我们的项目名称,然后点选基于开发板,开发板我们选择STM32H750-RT-ART-Pi,类型我们选择实例工程,示例选择我们所需要的flashLED,其他默认即可,因为板卡自带STLink所以调试器就选择STLink。 点击完成后,IDE会自动生成demo工程,既然是demo,那么我们暂时不需要写自己的代码就能实现功能了,首先我们点击debug按钮。说明一下这里的debug按钮是不会下载程序的,可以理解为编译俺就,点击就等于编译工程,看有没有语法错误。 OK,很明显,编译不出意外不会报错,我们把硬件接上,说明一下,烧写程序,我们要把调试线接在板卡的USB-DBG端,这个是STlink下载接口,如图, 在下载程序之前,我们点击配置按键,在download标签页里面确认一下片外flash启动算法,这也是我们为什么后续开发要基于demo程序的原因,可以直接利用这个算法,从片外flash启动程序。我们点击下载按钮即可把程序下载到板卡里面了。 到这里应该重新上电程序就能运行了,但是要注意,这时下载线要换个接口了,要接在USB-OTG端口,否则程序不会运行,这个不知道为啥,估计我太菜无法解释。 至此,可以看到,我们可以利用demo迅速开发我们相关应用,起码硬件上是调通了。后续会展示一些简单应用。
  • 热度 8
    2020-12-25 14:56
    2367 次阅读|
    2 个评论
    使用DMA 进行AD采样很方便,但需要事先设置好通道。如果有过程中希望修改通道,可以先做一个DeInit 然后设置不同的Rank // Adc 通道配置 选择 vdc vbat preu pred void ADC1_misc_Init(void) { ADC_ChannelConfTypeDef sConfig; HAL_ADC_DeInit(&hadc1); /**Common config */ hadc1.Instance = ADC1; hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE; hadc1.Init.ContinuousConvMode = ENABLE; hadc1.Init.DiscontinuousConvMode = DISABLE; hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc1.Init.NbrOfConversion = 4; if (HAL_ADC_Init(&hadc1) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } /**Configure Regular Channel */ sConfig.Channel = ADC_CHANNEL_12; // bdc sConfig.Rank = ADC_REGULAR_RANK_1; sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } /**Configure Regular Channel */ sConfig.Channel = ADC_CHANNEL_13; // vbat sConfig.Rank = ADC_REGULAR_RANK_2; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } /**Configure Regular Channel */ sConfig.Channel = ADC_CHANNEL_1; // preu sConfig.Rank = ADC_REGULAR_RANK_3; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } /**Configure Regular Channel */ sConfig.Channel = ADC_CHANNEL_7; // pred sConfig.Rank = ADC_REGULAR_RANK_4; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } } // adc1 通道配置 bub pos void ADC1_ir_Init(void) { ADC_ChannelConfTypeDef sConfig; HAL_ADC_DeInit(&hadc1); /**Common config */ hadc1.Instance = ADC1; hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE; hadc1.Init.ContinuousConvMode = ENABLE; hadc1.Init.DiscontinuousConvMode = DISABLE; hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc1.Init.NbrOfConversion = 2; if (HAL_ADC_Init(&hadc1) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } /**Configure Regular Channel */ sConfig.Channel = ADC_CHANNEL_5; // position sConfig.Rank = ADC_REGULAR_RANK_1; sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } /**Configure Regular Channel */ sConfig.Channel = ADC_CHANNEL_6; // bubble sConfig.Rank = ADC_REGULAR_RANK_2; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } } 在启动转换时,依据设置的通道数,选择不同的DMA空间 void StartADC1Misc(void){ HAL_ADC_Start_DMA(&hadc1, ADC1Buf.ValMem,ADCCNT*4); } void StartADC1IR(void){ HAL_ADC_Start_DMA(&hadc1, IRBuf.ValMem,ADCCNT*2); } 获取采样值的时候,找到对应的缓冲区 uint32_t AdcGetValue(uint8_t ch){ uint32_t temp,i; temp = 0; for(i = ADCCNT/2-5;i< ADCCNT/2+5;i++){ temp = temp+ (ADC1Buf.Val &0xFFF); } temp /= 10; return temp; } uint32_t AdcGetIRValue(uint8_t ch){ uint32_t temp,i; temp = 0; for(i = ADCCNT/2-5;i< ADCCNT/2+5;i++){ temp = temp+ (IRBuf.Val &0xFFF); } temp /= 10; return temp; }
  • 热度 2
    2020-12-17 09:11
    1743 次阅读|
    0 个评论
    【不用开发板学习STM32】7段数码管0~9定时显示(文末获取代码及工程文件)
    本实验是通过7个IO口控制一个共阳7段数码管,分别从0~9依次显示。时间间隔200ms刷新一次。系统时钟源是内部8MHz晶振,具体原因上一期已经讲述过了,时钟倍频位40MHz,使用了TIM2定时器,数码管刷新在TIM2中断函数中完成。同时利用systick来计时,控制一个LED灯间歇闪烁。工程师如果对STM32F10x系列怎么使用内部时钟有疑问可以参考这里的代码,都是在实际开发板上测试过,和用Proteus仿真结果是一致的。 TIM2初始化,这里设置是200ms进一次中断,系统时钟是40MHz,并且配置好TIM2的中断,代码如下: void bsp_InitTIM2(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; uint32_t usPeriod; /* 开启TIM2的时钟 */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); usPeriod = 2000; //重装载数值 200ms /* Time base configuration */ TIM_TimeBaseStructure.TIM_Period = usPeriod; TIM_TimeBaseStructure.TIM_Prescaler = 3999; //设置分频系数 TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //开启TIM2中断 TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE ); /* TIMx enable */ TIM_Cmd(TIM2, ENABLE); { /* 配置定时器中断 */ NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 4; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } } 代码及工程下载链接!! https://t.1yb.co/axri
相关资源
广告