cxhxy12345
cxhxy12345
This guy hasn't written anything yet

注册于 9 months ago

回答
337
文章
0
关注者
3

如果1ms要中断5次?你的can总线数据是不是太多了,can数据一次最少8个字节为一帧数据,如果1ms中断5次,那几本200us一次。操作系统的Tick最小也是1ms做一次任务切换,如果再低,系统效率会降低。如果你的数据每次不需要及时处理,可以考虑用DMA方式放入缓冲区中,再用任务去读取,这样可以一次性读取多个数据来处理,否则只有建议你不要用操作系统了~~~~

你因该是用于TCP上做一个sever和一个client吧,W5500可以支持8个独立端口的SOCKet通讯,也就是你可以用一个socket创建为服务端,开一个端口。再用一个socket做一个客户端。可以同时工作,没有问题~~~~

没有玩过实时视频图像通过TouchGFX,但我估计是玩不起来的,因为OV2640采集的图像需要前面做一个ISP处理,还要做图像格式转换,因为采集图像时YUV4:2:2格式,而TouchGFX是支持图片格式,这个是二个不同的概念。而且ART-PI的资源和CPU核也不具备处理实时视频的能力。
以上只是建议~~~

没有看过你说的文档中步骤建立中文库,但有几个建议给你
(1)他是不是建立的GUI的基础上做屏幕显示的
(2)中文字库是点针显示的,你移植程序中,需要注意它的点阵库在那里,是外部芯片读取的,还是内嵌在代码中的。看了你的截图,因该是外部做好内嵌到代码中的。
(3)显示屏是点阵屏,你需要了解该屏幕的主要寄存器参数,这样对你理解别人的文档有帮助,如果觉得浪费时间,就先直接移植它的全部代码后运行,这个时候看,如果只是没有中文,其它的图形显示都正常,则就查找它的字库位置
(4)中文字库建立后,在显示时,你要看它是16X6 ,还是8X12,或者是32X32,因为不同的点阵,C代码取值方式是不同的。这点特别需要注意,不然你的中文显示就是乱码

因该没有指向指定的类包含的头文件,看下你的include中是不是漏了.h文件

LittleFs和FatFs挂载在不同的设备上当然可以,但你必须面对的是二个不同文件系统之间的数据转换和目录查询,文件读写上系统部分开销是双倍的代价,而且针对文件系统的文件对象还有数据、格式转换的问题。
所以你的这个问题比较冷门,因为绝大多数的设备只会用一种文件系统来应对不同的文件处理。
如果自己对文件系统不是很深入地了解,建议你不要这样做,因为会碰到许多你无法咨询的问题,而且很浪费时间。
我猜想你主要是25Q128的存储不够才考虑用LittlesFS,如果换W25X64 有8M空间,因该就没有问题了,这样整个系统只要运行一个FatFs就可以了,而且W25X64与25Q128是pin对pin的,只要换芯片就可以了~~。

这个还要看不同的STM芯片的定时器太多,定时器用到的时钟是通过APB1和APB2时钟频率总线提供。所以用户可以根据自己的需要按RTT的要求自己定义即可。与定时器的最高频无关。
另外,多个定时器公用一个预分频寄存器和捕获比较寄存器是存在的,但这个是运用在外部信号输入的情况信号输入的情况下,如果只是做定时和计数用,那么你可以看手册,每个定时器都有独立对应的寄存器。
所以,如果你只是做定时器用,按RTT要求自己定义即可。

LWIP可以支持双网卡
硬件初始化时要区分两个网卡的MAC地址并且填充到netif块中。
数据流方向,判断返回的数据是要发送到哪个网卡,将数据拷贝到网卡发送缓冲区,然后发送。同理判断是哪个网卡接受到了数据,并将网卡接受缓冲区中的数据拷贝到netif块中。
注意:在发送数据时要判断是那个网卡,否则出现ping 二个网卡都能通的现象。另外在ip_route()函数是
找到默认的一个路由表中的第一个路由就直接返回了,所以二个网卡是同一个段时,要比较源地址来确认由
那个网卡来发送数据。
所以,如果你要实现双网卡,对LWIP的底层驱动函数还要做一些修改才可以。当然也要保证你有充足的内存可以被分配!

AT组件是AT协议的通讯组件,MQTT软件包是在TCP/IP基础上实现MQTT通讯,如果你要理解这二者的关系则是
用户<--->AT组件<--->MQtt协议包<---->TCP/IP协议包<---->网络链接层

               |<--------net组件---------------->|

这样就可以用AT命令发送数据/接受应答数据。
如果将net组件改成蓝牙、WIFI、Cat1、Nb_lot就可以实现这些模块的通讯功能。
官方提供的sample只是简单的通过finsh组件的msh模式测试对应的AT组件和IP模块,
at_exec_cmd(resp, "AT");//AT测试
result = at_exec_cmd(resp, "AT+CIFSR");//返回AT模块的IP地址
如果你想通过msh模式下与AT模块进行通讯,可以用at_cli.c文件中的at函数
具体执行如下:
image.png

上图中的AT模块挂在uart1,console控制台对应的串口是uart0
实现的AT client功能
如果你要做项目,则需要自己建立线程来执行对应的操作。

FreeModbus的不同波特率下有些高,有些低都出现接受错误,如果只是简单地设置RT_TICK_PER_SECOND,按照网上的经验的确可以解决一些问题,但根本的原因可能还是不了解,下面是以前看过的资料的记录,可以给你做个借鉴,阅读希望对你有帮助。
Freemodbus需要配合一个定时器使用,这是因为它是通过定时器超时来判断Modbus传输过程结束的,在Modbus协议中,以RTU模式为例,报文帧由时长至少为3.5个字符的空闲间隔区分,这个区间被称为t3.5,注意,这里是“至少”不是至多,也就是通信之间也不希望对方发的过快,所以在Freemodbus中对定时器就采用了类似于四舍五入的办法,比3.5个字符略微多一点的溢出时间。
image.png

一般的串口通信中,发送一个字符需要:1位起始位+8位数据位+1位校验位(可选)+1位停止位,总共11位,所以3.5个字符时间就是 3.5*11 = 38.5位,注意如果没有校验位就按10位计算。假设波特率是9600bps,那么传输1位的时间大约就是 1000/9600 = 0.10416667(ms)
这样,3.5个字符的时间就是 38.5位,也就是大约 4.01ms,这也就是定时器需要中断的时间,可以比这个时间略大一点点,所以Freemodus做了一个 特别巧妙的公式变量:
usTimerT35_50us = ( 7UL 220000UL ) / ( 2UL ulBaudRate )
这里,usTimerT35_50us表示 3.5个字符,对应 50us的倍数,以波特率9600计算,刚刚理论计算为4ms左右,4000us/50us = 80
那么这个公式的计算结果是:usTimerT35_50us = ( 7UL 220000UL ) / ( 2UL ulBaudRate ) = 7220000/(29600) = 80.2,这个值是无符号整型,所以就是80
那么算出 80 以后怎么用呢,80代表的是80个 50us,为了移植方便,所以都用 50us作为基准,在具体使用的时候,刚说到要比t3.5稍微大点,大太多,反应慢,容易出错,给了一种方法:
usTimeoutMS = ( usTim1Timerout50us + 10 ) / 20;
其中 usTimeoutMS 就是要延时的ms数,还是以9600为例,那么定时器溢出时间为  (80+10)/20 = 4ms,然后移植者再根据自己的处理器,设置4ms的定时器溢出即可。
好了,这样就可以到移植代码中找到定时器设置函数做相关的配置。

可以用以下代码试下:

cJSON *object = cJSON_GetObjectItem(root, "params");
for(int i=0; i<cJSON_GetArraySize(object); i++){//遍历键值对
    cJSON * item = cJSON_GetArrayItem(object, i);
    printJson(item);
}

建议用固定键值,这样在MCU上会省很多时间,

(1)如果你的时间上要求不是很高,可以创建一个线程后

while(1){
    ...你的任务
    rt_thread_mdelay(20);

如果你把这个线程将优先级设置为最高,则基本也可以满足要求
(2)用定时器,不管是硬件还是软件,你需要创建一个信号量,在定时器函数中释放该信号量,然后在你的
任务线程中等待获取这个信号量,一旦获取你就可以读数据。
(3)如果你对时间要求达到us级,并且时钟不高的情况下,那基本只能在中断中读取数据到缓冲中,然后发送信号给处理线程处理数据结果。
第2种和第3种基本一致,只是定时器中是否放入读设备的操作,具体情况还要看你的程序框架设计

static是静态变量,普通的局部变量会随着函数体的结束而结束,但static不会,使用static修饰符定义的静态局部变量,即使在声明时未赋初值,编译器也会把它初始化为0。且静态局部变量存储于进程的全局数据区,即使函数返回,它的值也会保持不变。在arm编译后放在RW Data段,即bss段中。
现在解释下为什么句柄不能用static,因为它还是一个局部变量,我们在项目中的句柄是一个需要在函数体外被引用的变量,因此它必须是public。

nano挂的finsh组件使用的串口因该是中断方式(串口中断,DMA中断二选一),
组件中有历史命令的设置

define FINSH_USING_HISTORY //使能历史命令

define FINSH_HISTORY_LINES 5 //历史命令最大记录数

再msh模式下,通过键盘的向上按键可以翻看历史命令
在finsh中的reboot命令就是重新启动系统的操作,你需要自己做一个复位函数例程:在里面加一句
rt_hw_cpu_reset()就可以了。
然后通过MSH_CMD_EXPORT()导出到msh命令列表中。

回到
顶部

发布
问题

投诉
建议