HK32F030MF4P6与昆仑通态触摸屏的modbus通讯程序

内容分享20小时前发布 闫跃龙
0 1 0

第一步:TIME2定时器的初始化

#include “hk32f030m.h”

#include “hk32f030m_tim.h”

void time2_init() //初始化定时器

{

uint16_t PrescalerValue = 0;

PrescalerValue = (uint16_t) ((SystemCoreClock ) / 32000000) – 1;//配置频率为32M

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //打开TIM2的时钟

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; //定义定时器配置结构体

NVIC_InitTypeDef NVIC_InitStructure; //定义中断向量结构体


TIM_TimeBaseStructure.TIM_Period = 10000; //溢出上限值


TIM_TimeBaseStructure.TIM_Prescaler = 31; //分频系数1-65535之间


//TIM_TimeBaseStructure.TIM_ClockDivision = 0; //时钟分频因子,外部时钟源才有用


TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数

TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //初始化定时器结构体

TIM_PrescalerConfig(TIM2, PrescalerValue, TIM_PSCReloadMode_Immediate);

/* TIM Interrupts enable */

//是否需要在此处增加一个清除定时器中断标志位的命令待定

TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); //开启定时计数器中断

/* TIM3 enable counter */

TIM_Cmd(TIM2, ENABLE); //使能计数器

//配置定时器的中断优先级


NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //设置中断来源


NVIC_InitStructure.NVIC_IRQChannelPriority = 1; //设置优先级为0


NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能

NVIC_Init(&NVIC_InitStructure); //初始化中断向量结构体

}

第二步:串口初始化

#include “gpio_init.h”

#include “hk32f030m.h”

#include “hk32f030m_usart.h”

#include “uart.h”

void uart_init(void)

{

USART_InitTypeDef m_usart;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

m_usart.USART_BaudRate = 9600;


m_usart.USART_HardwareFlowControl =
USART_HardwareFlowControl_None; //硬件流控制无

m_usart.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //工作模式收发一体

m_usart.USART_Parity = USART_Parity_No; //校验位无

m_usart.USART_StopBits = USART_StopBits_1; //停止位1位

m_usart.USART_WordLength = USART_WordLength_8b; //数据字长8位

USART_Init(USART1, &m_usart);

USART_Cmd(USART1, ENABLE);

USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //串口接收中断使能

//IRQ,此处是否需要定义结构体并初始化待定

NVIC_SetPriority(USART1_IRQn,0); //中断来源

NVIC_EnableIRQ(USART1_IRQn); //使能中断向量

}

void USART_SendByte(uint8_t ch)

{

while((USART1->ISR & USART_ISR_TXE) == 0);

USART1->TDR = ch;

}

void USART_SendStringLen(uint8_t *p,uint16_t len)

{

while(len–)

{

USART_SendByte(*(p++));

}

}

第三步:定时器中断处理程序和串口中断处理程序

void USART1_IRQHandler(void)

{

uint8_t ch_rx_test;

if((USART1->ISR & USART_ISR_RXNE) != 0)

{

//GPIO_SetBits(GPIOA,GPIO_Pin_2);

//USART_ITConfig(USART1, USART_IT_RXNE, DISABLE); //关闭串口接收中断

ch_rx_test = USART1->RDR; //RXNE auto clear at read after标志位在读取后自动清除

modbusa.rcbuf[modbusa.recount++] = ch_rx_test; //把数据存入接收缓冲数组

modbusa.timout = 0; //定时计数值清零

if(modbusa.recount == 1) //如果收到了第一个字节数据

{

modbusa.timrun = 1; //启动计数

}

}

//USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //打开串口接收中断

}

void TIM2_IRQHandler(void)

{

//GPIO_ResetBits(GPIOA,GPIO_Pin_2);

if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)

{

if(modbusa.timrun != 0) //判断是否启动计数

{

modbusa.timout++; //计数值累加

if(modbusa.timout >= 8) //判断累加是否达到时间,就是判断两次串口接收数据的间隔时间

{

modbusa.timrun = 0; //结束计数

modbusa.reflag = 1; //收到一帧数据的标志位置一,开始处理数据

}

}

TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //清除定时器中断标志位

}

}

第四步:modbus处理程序

1、头文件

#ifndef __modbus_H

#define __modbus_H

#endif

#include “hk32f030m.h”

typedef struct

{

uint8_t myadd; //本机地址

uint8_t rcbuf[64]; //接收缓冲区

uint16_t timout; //数据接收两个字节的间隔时间计数

uint8_t recount; //接收到的字节个数

uint8_t timrun; //定时器是否开始计时标志

uint8_t reflag; //收到一帧标志

uint8_t sendbuf[64]; //发送缓冲区

}MODBUS;

extern MODBUS modbusa; //定义全局变量结构体

void modbus_event(void);

void modbud_fun3(void);

void modbud_fun6(void);

2、c文件

#include “hk32f030m.h”

#include “modbus.h”

#include “CRC16.h”

#include “uart.h”

MODBUS modbusa;

void modbus_event(void)

{

modbusa.myadd = 1;

uint16_t crc;

uint16_t rccrc;

if(modbusa.reflag == 0) //判断帧标志位,如果为0则直接退出函数

{

return;

}

crc = MB_CRC16(&modbusa.rcbuf[0],modbusa.recount-2); //计算校验码

rccrc = modbusa.rcbuf[modbusa.recount-2]*256+modbusa.rcbuf[modbusa.recount-1]; //接收的校验码

if(crc == rccrc) //校验码比较

{

if(modbusa.rcbuf[0] == modbusa.myadd) //从机地址比较

{

//USART_SendByte(0X55);

//USART_SendByte(modbusa.rcbuf[1]);

switch(modbusa.rcbuf[1]) //功能码识别

{

case 0: break;

case 1: break;

case 2: break;

case 3: modbud_fun3(); break; //执行3号功能码响应函数

case 6: modbud_fun6(); break; //执行6号功能码响应函数

case 7: break;

case 16: break;

}

}

else if(modbusa.rcbuf[0] == 0) //广播地址无响应

{

}

}

modbusa.recount = 0; //接收字节数清零

modbusa.reflag = 0; //帧标志位清零

}

void modbud_fun3(void)

{

extern uint16_t reg[];

uint16_t regadd;

uint16_t reglen;

uint16_t byte;

uint16_t i,j;

uint16_t crc;

regadd = modbusa.rcbuf[2]*256+modbusa.rcbuf[3]; //计算要读取的寄存器起始地址

reglen = modbusa.rcbuf[4]*256+modbusa.rcbuf[5]; //计算要读取的寄存器数量

i = 0;

modbusa.sendbuf[i++] = modbusa.myadd; //本机地址

modbusa.sendbuf[i++] = 0x03; //功能码

byte = reglen*2; //计算要返回的字节数

//modbusa.sendbuf[i++] = byte/256; //除以256相当于右移8位,取高8位来使用

modbusa.sendbuf[i++] = byte%256; //字节数写入发送缓冲区,取余256相当于直接用低8位

for(j=0;j<reglen;j++) //读取的数据循环写入发送缓冲区

{

modbusa.sendbuf[i++] = reg[regadd+j]/256;

modbusa.sendbuf[i++] = reg[regadd+j]%256;

}

crc = MB_CRC16(modbusa.sendbuf,i); //计算校验码

modbusa.sendbuf[i++] = crc/256; //校验码写入发送缓冲区

modbusa.sendbuf[i++] = crc%256;

for(j=0;j<i;j++) //循环发送数据到串口

{

USART_SendByte(modbusa.sendbuf[j]);

}

}

void modbud_fun6(void)

{

extern uint16_t reg[];

uint16_t regadd;

uint16_t val;

uint16_t i,j;

uint16_t crc;

i = 0;

regadd = modbusa.rcbuf[2]*256+modbusa.rcbuf[3]; //计算要写入的寄存器起始地址

val = modbusa.rcbuf[4]*256+modbusa.rcbuf[5]; //计算要修改后的值

reg[regadd] = val; //修改本机地址的值

modbusa.sendbuf[i++] = modbusa.myadd; //本机地址

modbusa.sendbuf[i++] = 0x06; //功能码

modbusa.sendbuf[i++] = regadd/256; //除以256相当于右移8位,取高8位来使用

modbusa.sendbuf[i++] = regadd%256; //字节数写入发送缓冲区,取余256相当于直接用低8位

modbusa.sendbuf[i++] = val/256; //高位值

modbusa.sendbuf[i++] = val%256; //低位值

crc = MB_CRC16(modbusa.sendbuf,i); //计算校验码

modbusa.sendbuf[i++] = crc/256; //校验码写入发送缓冲区

modbusa.sendbuf[i++] = crc%256;

for(j=0;j<i;j++) //循环发送数据到串口

{

USART_SendByte(modbusa.sendbuf[j]);

}

}

第五步:CRC16校验码计算程序

#include “hk32f030m.h”

uint16_t MB_CRC16(uint8_t *_pushMsg,uint8_t _usDataLen)

{

// CRC 高位字节值表

static const uint8_t auchCRCHi[] = {

0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,

0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,

0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,

0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,

0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,

0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,

0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,

0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,

0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,

0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,

0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,

0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,

0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,

0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,

0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,

0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,

0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,

0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,

0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,

0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,

0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,

0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,

0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,

0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,

0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,

0x80, 0x41, 0x00, 0xC1, 0x81, 0x40

} ;

// CRC 低位字节值表

static const uint8_t auchCRCLo[] = {

0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,

0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,

0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,

0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,

0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,

0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,

0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,

0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,

0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,

0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,

0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,

0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,

0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,

0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,

0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,

0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,

0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,

0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,

0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,

0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,

0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,

0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,

0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,

0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,

0x44, 0x84, 0x85,0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,

0x43, 0x83, 0x41, 0x81, 0x80, 0x40

};

uint8_t uchCRCHi = 0xFF;

uint8_t uchCRCLo = 0xFF;

uint16_t uIndex;

while(_usDataLen–)

{

uIndex = uchCRCLo ^ *_pushMsg++;

uchCRCLo = uchCRCHi^auchCRCHi[uIndex];

uchCRCHi = auchCRCLo[uIndex];

}

return (uchCRCHi<<8|uchCRCLo);

}

第六步:主程序

#include “hk32f030m.h”

#include “hk32f030m_gpio.h”

#include “uart.h”

#include “string.h”

#include “gpio_init.h”

#include “hk32f030m_usart.h”

#include “modbus.h”

#include “time2.h”

static void ledGpioToggle(void);

static void softWareDelay(void);

#define X0 GPIO_Pin_7

#define X1 GPIO_Pin_6

#define Y0 GPIO_Pin_4

#define RUNLED GPIO_Pin_2

uint16_t reg[100];

int main(void)

/* Infinite loop */

{

gpio_init();

uart_init();

softWareDelay();

time2_init();

while (1)

{

modbus_event();

if(GPIO_ReadInputDataBit(GPIOC,X0)==0)

{

GPIO_SetBits(GPIOD,Y0);

reg[1]++;

}

if(GPIO_ReadInputDataBit(GPIOC,X1)==0)

{

GPIO_ResetBits(GPIOD,Y0);

reg[0]++;

}

}

GPIO_SetBits(GPIOA,RUNLED); //这句指令永远执行不到,警告

}

static void ledGpioToggle(void)

{

GPIOC->ODR ^= GPIO_Pin_7;

}

static void softWareDelay(void)

{

uint16_t i;

uint16_t j;

for(i=0;i<500;i++)

{

for(j=0;j<1000;j++)

{

__NOP();

}

}

}

© 版权声明

相关文章

1 条评论

  • 头像
    兜馨儿 读者

    不懂哦

    无记录
    回复