本帖最后由 aple0807 于 2022-7-2 19:57 编辑
首先感谢论坛提供的开发板进行学习,N32G430是接触国民技术的第二款芯片,拿到板子先添加RTX操作系统及基本的外设测试。整体用法和STM32基本一致,但N32G430提供了更灵活的外设管脚映射,同一外设提供了更多的管脚选择方案。
RTX作为arm官方RTOS,直接从KEIL安装目录复制出来添加到工程即可,配置也比较简单,本次测试os tick配置为500Hz。对于高速MCU来说,使用RTOS可以显著提高MCU的运转效率,能有效解决一些外设对系统的阻塞。
分享一个IO配置模板程序,个人感觉这样更直观一些
typedef const struct
{
GPIO_Module *port;
uint32_t mode;
uint32_t pull;
uint32_t rate;
uint32_t current;
uint32_t alt;
uint32_t val_init;
uint32_t pin;
} gpio_init_cfg_type;
static gpio_init_cfg_type gpio_cfg[] = {
{GPIOA, GPIO_MODE_AF_PP, GPIO_NO_PULL, GPIO_SLEW_RATE_FAST, GPIO_DS_8MA, GPIO_AF5_USART1, 1, GPIO_PIN_9},
{GPIOA, GPIO_MODE_AF_PP, GPIO_PULL_UP, GPIO_SLEW_RATE_FAST, GPIO_DS_8MA, GPIO_AF5_USART1, 1, GPIO_PIN_10},
{GPIOB, GPIO_MODE_AF_PP, GPIO_NO_PULL, GPIO_SLEW_RATE_FAST, GPIO_DS_8MA, GPIO_AF10_UART3, 1, GPIO_PIN_10},
{GPIOB, GPIO_MODE_AF_PP, GPIO_PULL_UP, GPIO_SLEW_RATE_FAST, GPIO_DS_8MA, GPIO_AF10_UART3, 1, GPIO_PIN_11},
{GPIOB, GPIO_MODE_AF_PP, GPIO_NO_PULL, GPIO_SLEW_RATE_FAST, GPIO_DS_8MA, GPIO_AF7_UART4, 1, GPIO_PIN_0},
{GPIOB, GPIO_MODE_AF_PP, GPIO_PULL_UP, GPIO_SLEW_RATE_FAST, GPIO_DS_8MA, GPIO_AF7_UART4, 1, GPIO_PIN_1},
{GPIOA, GPIO_MODE_OUT_PP, GPIO_NO_PULL, GPIO_SLEW_RATE_FAST, GPIO_DS_8MA, 0, 1, GPIO_PIN_15},
{GPIOB, GPIO_MODE_OUT_PP, GPIO_NO_PULL, GPIO_SLEW_RATE_FAST, GPIO_DS_8MA, 0, 1, GPIO_PIN_3},
{GPIOB, GPIO_MODE_OUT_PP, GPIO_NO_PULL, GPIO_SLEW_RATE_FAST, GPIO_DS_8MA, 0, 1, GPIO_PIN_4},
};
void bsp_gpio_init(void)
{
int index;
// clock enable
RCC_APB2_Peripheral_Clock_Enable(RCC_APB2_PERIPH_AFIO);
RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOA);
RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOB);
RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOC);
RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOD);
for(int index = 0;index < sizeof(gpio_cfg)/sizeof(gpio_cfg[0]);index++)
{
GPIO_InitType GPIO_InitStructure;
GPIO_Structure_Initialize(&GPIO_InitStructure);
GPIO_InitStructure.Pin = gpio_cfg[index].pin;
GPIO_InitStructure.GPIO_Mode = gpio_cfg[index].mode;
GPIO_InitStructure.GPIO_Current = gpio_cfg[index].current;
GPIO_InitStructure.GPIO_Alternate = gpio_cfg[index].alt;
GPIO_InitStructure.GPIO_Slew_Rate = gpio_cfg[index].rate;
GPIO_InitStructure.GPIO_Pull = gpio_cfg[index].pull;
GPIO_Peripheral_Initialize(gpio_cfg[index].port, &GPIO_InitStructure);
if(GPIO_InitStructure.GPIO_Mode == GPIO_MODE_OUT_PP || GPIO_InitStructure.GPIO_Mode == GPIO_MODE_OUT_OD)
{
if(gpio_cfg[index].val_init)
GPIO_Pins_Set(gpio_cfg[index].port, gpio_cfg[index].pin);
else
GPIO_Pins_Reset(gpio_cfg[index].port, gpio_cfg[index].pin);
}
}
}
本示例配置UART1,UART3,UART4的管脚,UART1作为调试打印端口,UART和UART4分别做MODBUS主机和从机。
modbus用现成的协议栈,只需要修改端口及定时器管理即可。端口部分主要是初始化和中断处理,定时器在1ms系统定时器中计数处理。
modbus串口初始化
static void mb_port_Init(mb_mode_type mbMode, uint32_t ulBaudRate, mb_parity_type eParity)
{
USART_InitType cfg;
mb_port_hal_cfg();
mbObjInit(mbMode);
mb_byte_send = mb_rtu_byte_send;
cfg.Mode = USART_MODE_RX | USART_MODE_TX;
cfg.HardwareFlowControl = USART_HFCTRL_NONE;
cfg.BaudRate = ulBaudRate;
if (mbMode == MB_RTU_MASTER || mbMode == MB_RTU_SLAVE)
{
// rtu mode
if (MB_PAR_NONE == eParity)
{
cfg.WordLength = USART_WL_8B;
cfg.StopBits = USART_STPB_2;
cfg.Parity = USART_PE_NO;
}
else if (MB_PAR_NONE_1S == eParity)
{
cfg.WordLength = USART_WL_8B;
cfg.StopBits = USART_STPB_1;
cfg.Parity = USART_PE_NO;
}
else if (MB_PAR_ODD == eParity)
{
cfg.WordLength = USART_WL_9B;
cfg.StopBits = USART_STPB_1;
cfg.Parity = USART_PE_ODD;
}
else
{
cfg.WordLength = USART_WL_9B;
cfg.StopBits = USART_STPB_1;
cfg.Parity = USART_PE_EVEN;
}
mbObj.run_st.bits.rtu_mode = 1;
}
else
{
mb_byte_send = mb_asc_byte_send;
// asc mode
if (MB_PAR_NONE == eParity)
{
cfg.WordLength = USART_WL_8B;
cfg.StopBits = USART_STPB_1;
cfg.Parity = USART_PE_NO;
}
else if (MB_PAR_NONE_1S == eParity)
{
cfg.WordLength = USART_WL_8B;
cfg.StopBits = USART_STPB_1;
cfg.Parity = USART_PE_NO;
}
else if (MB_PAR_ODD == eParity)
{
cfg.WordLength = USART_WL_8B;
cfg.StopBits = USART_STPB_1;
cfg.Parity = USART_PE_ODD;
}
else
{
cfg.WordLength = USART_WL_8B;
cfg.StopBits = USART_STPB_1;
cfg.Parity = USART_PE_EVEN;
}
mbObj.run_st.bits.rtu_mode = 0;
}
// rtu timer
if (mbObj.run_st.bits.rtu_mode == 0)
{
mbObj.rtu_timer_sv = 240;
mbObj.timeout_set = 500;
}
else
{
if (ulBaudRate > 19200)
{
mbObj.rtu_timer_sv = 3;
}
else
{
mbObj.rtu_timer_sv = (com_timer_cal(ulBaudRate, (35 * 11 + 9) / 10, 300, 12000) + 99) / 100;
}
}
USART_Initializes(mbPORT, &cfg);
USART_Enable(mbPORT);
nvic_irq_set(mbURT_IRQn, 0x06, 1);
mb_tx1_rx0_enable(0);
}
isr服务程序
void mbISR()
{
volatile uint32_t IntSt;
volatile uint8_t Data;
mbObj.timeout_cnt = 0;
IntSt = mbPORT->STS;
if (IntSt & USART_STS_RXDNE)
{
Data = UART_RCV_DAT();
if ((IntSt & UART_RX_ERR_FLAG) != 0)
{
if (mbObj.rcv_cnt >= 1)
{
mbObj.err_st.bits.hal = 1;
}
}
mb_data_rcv(&mbObj, Data);
}
else if ((mbObj.snd_size <= mbObj.snd_cnt) && (IntSt & USART_STS_TXC))
{
mb_send_end(&mbObj);
mb_tx1_rx0_enable(0);
UART_TX_TC_CLR();
}
else if (IntSt & USART_STS_TXDE)
{
if (mb_data_send(&mbObj, mb_byte_send, 1))
{
UART_TX_TC_EN();
}
}
else
{
}
}
下面附上测试工程,欢迎讨论。
本测试将开发板PB0连接PB11,PB1连接PB10,可令modbus主机和从机进行通信。
===========================================================================
内部资源分配:
===========================================================================
UART1: 调试信息打印
UART3: MODBUS 主机 PB10, PB11
UART4: MODBUS 从机 PB0, PB1
===========================================================================
demo-n32g430.rar
(2.26 MB)
另外顺便调了一下串口打印,上电按按键结果如下:
@安小芯 |
 共1人点赞
|