本帖最后由 袁胜富 于 2022-7-7 11:53 编辑
一、概述
初次认识国民技术是在去年左右吧,开始买过N32G452RCL7,64Pin的芯片,由于某种原因没有用在实际项目中,非常遗憾。但一次在国民微信公众号看到新发布的N32G430C8L7,于是找到芯片手册,发现这款芯片性价比非常高,拥有128MHZ运行频率,4路串口,16路独立ADC,其他外设也还有很多,就不一一介绍了,大家有兴趣的话,可以去看看这个芯片的Datasheet。在日常中,常常需要用到引脚封装少的芯片做一些小的电子测试治具,会用到很多个串口,发现这款芯片满足我的需求,是我比较满意的芯片,64KByte的Flash和16KByte的SRAM,适合跑一些小型的实时操作系统,比如TencentOS-Tiny。本文将介绍此操作系统在N32G430C8L7上的移植运行及跑Modbus-Master。Modbus-Master支持Modbus function 0x01 Read Coils、Modbus function 0x02 Read Discrete Inputs、Modbus function 0x03 Read Holding Registers、Modbus function 0x04 Read Input Registers、Modbus function 0x05 Write Single Coil、Modbus function 0x06 Write Single Register、Modbus function 0x0F Write Multiple Coils、Modbus function 0x10 Write Multiple Registers、Modbus function 0x16 Mask Write Register、Modbus function 0x17 Read Write Multiple Registers,可以满足一般场景应用了。话不多说开始讲解系统适配和Modbus-Master的适配。 二、适配教程 到Gitee下载,TencentOS-Tiny的Gitee源码地址:https://gitee.com/Tencent/TencentOS-tiny.git,得到源码后,从国民技术的官方例程包中抽取芯片开发固件库。从源码中复制出。最终得到以下图片展示文件
arch文件各级目录,里面包含需要的ARM Cortex-M4平台支持文件
kernel文件各级目录,是TencentO tiny的内核实现代码
osal文件各级目录,是TencentOS tiny提供的cmsis os 适配
TOS_CONFIG文件各级目录,是TencentOS tiny配置的配置文件,可实现功能的选择
Modbus_Master文件各级目录,是Modbus_Master的实现源码
Boad文件各级目录
Keil工程结构
需要注意的是需要在n32g430_it.c文件下包含#include "tos_k.h"
加入如下代码
/**
*\*\name SysTick_Handler.
*\*\fun This function handles SysTick Handler.
*\*\param none
*\*\return none
**/
void SysTick_Handler(void)
{
if (tos_knl_is_running())
{
tos_knl_irq_enter();
tos_tick_handler();
tos_knl_irq_leave();
}
}
由于ST的库里面系统时钟用SystemCoreClock,而N32G430C8L7库用SystemClockFrequency表示,这点需要注意。
Modbus-Master用到了USART1,配置时需要配置一下,要是用到别的串口,好知道在那里修改。
1.在trans_recieve_buff_control.c文件中修改接收串口数据的串口对象
/****************************************************************************************************/
/*下面是与硬件接口层相关联的部分,根据不同处理器的处理方式进行移植*/
/**
* @brief 获取接收寄存器里面的数值
* @param
* @note
* @retval void
* @author xiaodaqi
*/
uint8_t Modbus_Master_GetByte(uint8_t *getbyte)
{
*getbyte = USART_Data_Receive(USART1); //接收一个字节
return 1;
}
2.修改串口发送数据的串口对象
/**
* @brief 将数据包发送出去
* @param
* @note
* @retval void
* @author xiaodaqi
*/
uint8_t Modbus_Master_Write(uint8_t *buf,uint8_t length)
{
for(int i=0; i<length; i++)
{
while (USART_Flag_Status_Get(USART1, USART_FLAG_TXDE) == RESET);
USART_Data_Send(USART1, *buf++);
}
return 1;
}
3.1ms周期的定时器用操作系统的时基函数tos_systick_get()
/**
* @brief 1ms周期的定时器
* @param
* @note
* @retval void
* @author xiaodaqi
*/
uint32_t Modbus_Master_Millis(void)
{
return tos_systick_get();
}
4.串口中断在n32g430_it.c加入#include "trans_recieve_buff_control.h"实现,需要如下代码
void USART1_IRQHandler(void)
{
char CH;
if (tos_knl_is_running())
{
tos_knl_irq_enter();
if (USART_Interrupt_Status_Get(USART1, USART_INT_RXDNE) != RESET)
{
/* Read one byte from the receive data register */
Modbus_Master_Rece_Handler();
USART_Interrupt_Status_Clear(USART1,USART_INT_RXDNE);//clear USART_INT_RXDNE flag
}
tos_knl_irq_leave();
}
}
至此,全部代码适配讲解完毕,鉴于水平有限,请大家多多指教。
下面创建三个任务,一个任务用来LED闪灯,一个任务用来实现按钮按下实现LED翻转和关闭LED,最后一个用来实现Modbus-Master的数据处理。下面main.c代码
#include "main.h"
#include "bsp_led.h"
#include "bsp_delay.h"
#include "key.h"
#include "uart.h"
#include "stdio.h"
#include "tos_k.h"
#include "modbus_master.h"
k_task_t task1;
k_stack_t task1_stack[1024];
k_task_t Modbus_Master_ProcessTask;
k_stack_t Modbus_Master_ProcessTask_stack[1024];
k_task_t task2;
k_stack_t task2_stack[1024];
void Modbus_Master_Process(void *arg)
{
while(1)
{
tos_task_delay(10);
ModbusMaster_readHoldingRegisters(0x01,0x10,2);//读保持寄存器 0x03功能码
tos_task_delay(10);
ModbusMaster_readInputRegisters(2, 0x0021, 0x0002);
}
}
void task1_fun(void *arg)
{
while (1)
{
if(WakeUp_Key)
{
tos_task_delay(10);
if(WakeUp_Key)
{
PAout(1) = ~PAout(1);
PAout(7) = ~PAout(7);
}
while(WakeUp_Key)
{
tos_task_delay(1);
}
}
if(!Key1)
{
tos_task_delay(10);
if(!Key1)
{
PAout(1) = 0;
}
while(!Key1)
{
tos_task_delay(1);
}
}
if(!Key2)
{
tos_task_delay(10);
if(!Key2)
{
PAout(7) = 0;
}
while(!Key2)
{
tos_task_delay(1);
}
}
tos_task_delay(1);
}
}
void task2_fun(void *arg)
{
while (1)
{
PAout(1) = ~PAout(1);
PAout(7) = ~PAout(7);
tos_task_delay(500);
}
}
/**
*\*\name main.
*\*\fun main function.
*\*\param none.
*\*\return none.
**/
int main(void)
{
k_err_t err;
NVIC_Priority_Group_Set(NVIC_PER2_SUB2_PRIORITYGROUP);
SysTick_Delay_Ms(500);
/* Initialize Led1~Led3 as output push-pull mode */
LED_Initialize(LED1_GPIO_PORT, LED1_GPIO_PIN | LED2_GPIO_PIN);
/* Turn off Led1~Led3 */
LED_Off(LED1_GPIO_PORT, LED1_GPIO_PIN | LED2_GPIO_PIN);
//Key Inition
Key_Init();
//usart1 Inition
UART1_Init(115200);
//Modbus Inition
ModbusMaster_begin();
printf(" Welcome to TencentOS Tiny!\r\n");
tos_knl_init(); // TencentOS Tiny kernel initialize
err = tos_task_create(&task1,
"task1",
task1_fun,
NULL,
3,
task1_stack,
1024,
0);
if(err != K_ERR_NONE)
printf("TencentOS Create task1 fail! code : %d \r\n",err);
err = tos_task_create(&task2,
"task2",
task2_fun,
NULL,
3,
task2_stack,
1024,
0);
if(err != K_ERR_NONE)
printf("TencentOS Create task2 fail! code : %d \r\n",err);
err = tos_task_create(&Modbus_Master_ProcessTask,
"Modbus_Master_ProcessTask",
Modbus_Master_Process,
NULL,
3,
Modbus_Master_ProcessTask_stack,
1024,
0);
if(err != K_ERR_NONE)
printf("TencentOS Create Modbus_Master_Process fail! code : %d \r\n",err);
tos_knl_start(); // Start TencentOS Tiny
while(1)
{
}
}
下图是串口发送的modbus数据包
工程文件在附件中
三、使用此开发板的感受
1.板子资源非常丰富,芯片性价比非常高。
2.开发基于Keil来说,库还是简单易懂的。
3.例程丰富,芯片资料全部开放给ii客户,不像某些国产厂家寄存器手册都藏着掖着,感兴趣的朋友可以试试这颗芯片,目前国民技术已经量产的,保证10年供货,不会担心停产。
4.国民技术专心做国产芯,以后会一如既往的支持国民技术。@安小芯 @21ic大掌柜
|