-
2020-12-16 15:17:30
main.c
//IO18---IO23,普通IO口,输入状态,判断是不是0,是0,说明垃圾满 #include "sleep.h" #include <stdio.h> #include <unistd.h> #include "kpu.h" #include <platform.h> #include <printf.h> #include <string.h> #include <stdlib.h> #include "bsp.h" #include <sysctl.h> #include "plic.h" #include "utils.h" #include <float.h> #include "uarths.h" #include "fpioa.h" #include "lcd.h" #include "pin_config.h" #include "dvp.h" #include "ov2640.h" #include "uarths.h" #include "image_process.h" #include "board_config.h" #include "nt35310.h" #include "gpiohs.h" #include "gpio.h" #include "spi.h" #define INCBIN_STYLE INCBIN_STYLE_SNAKE #define INCBIN_PREFIX #include "incbin.h" #include "image.h" #include <string.h> //cmake .. -DPROJ=keypad -G "MinGW Makefiles" #define xmmpul 2 //1000个脉冲,是1mm,测试可以修改 #define PLL0_OUTPUT_FREQ 1000000000UL #define PLL1_OUTPUT_FREQ 400000000UL #define PLL2_OUTPUT_FREQ 45158400UL volatile uint8_t ircut_value = 0x01; volatile uint8_t r_ircut_value = 0x00; volatile uint32_t g_ai_done_flag; volatile uint8_t g_dvp_finish_flag; static image_t kpu_image, display_image, crop_image; extern const unsigned char gImage_image[] __attribute__((aligned(128))); static uint16_t lcd_gram[320 * 240] __attribute__((aligned(32))); kpu_model_context_t task1; INCBIN(model, "m.kmodel");//m.kmodel在src里面对应的要cmake的文件夹内 #define min(a,b) (((a) < (b)) ? (a) : (b)) static void ai_done(void* userdata) { g_ai_done_flag = 1; float *features; size_t count; kpu_get_output(&task1, 0, (uint8_t **)&features, &count); count /= sizeof(float); size_t i; for (i = 0; i < count; i++) { if (i % 64 == 0) printf("\n"); printf("%f, ", features[i]); } printf("\n"); } static int dvp_irq(void *ctx) { if (dvp_get_interrupt(DVP_STS_FRAME_FINISH)) { dvp_config_interrupt(DVP_CFG_START_INT_ENABLE | DVP_CFG_FINISH_INT_ENABLE, 0); dvp_clear_interrupt(DVP_STS_FRAME_FINISH); g_dvp_finish_flag = 1; } else { dvp_start_convert(); dvp_clear_interrupt(DVP_STS_FRAME_START); } return 0; } /** * Function hardware_init * @author Gengyue * @date 2020.05.27 * @brief 硬件初始化,绑定GPIO口 * @param[in] void * @param[out] void * @retval void * @par History 无 */ void hardware_init(void) { fpioa_set_function(PIN_LED_0, FUNC_LED0); fpioa_set_function(PIN_LED_1, FUNC_LED1); fpioa_set_function(PIN_LJT_0, FUNC_LJT0); fpioa_set_function(PIN_LJT_1, FUNC_LJT1); fpioa_set_function(PIN_LJT_2, FUNC_LJT2); fpioa_set_function(PIN_LJT_3, FUNC_LJT3); fpioa_set_function(PIN_LJT_4, FUNC_LJT4); fpioa_set_function(PIN_LJT_5, FUNC_LJT5); fpioa_set_function(PIN_DIR_0, FUNC_DIR0); fpioa_set_function(PIN_PUL_0, FUNC_PUL0); fpioa_set_function(PIN_DIR_1, FUNC_DIR1); fpioa_set_function(PIN_PUL_1, FUNC_PUL1); /* Init DVP IO map and function settings */ fpioa_set_function(OV_RST_PIN, FUNC_CMOS_RST); fpioa_set_function(OV_PWDN_PIN, FUNC_CMOS_PWDN); fpioa_set_function(OV_XCLK_PIN, FUNC_CMOS_XCLK); fpioa_set_function(OV_VSYNC_PIN, FUNC_CMOS_VSYNC); fpioa_set_function(OV_HREF_PIN, FUNC_CMOS_HREF); fpioa_set_function(OV_PCLK_PIN, FUNC_CMOS_PCLK); fpioa_set_function(OV_SCCB_SCLK_PIN, FUNC_SCCB_SCLK); fpioa_set_function(OV_SCCB_SDA_PIN, FUNC_SCCB_SDA); /* Init SPI IO map and function settings */ fpioa_set_function(LCD_DC_PIN, FUNC_LCD_DC); fpioa_set_function(LCD_CS_PIN, FUNC_LCD_CS); fpioa_set_function(LCD_RW_PIN, FUNC_LCD_RW); fpioa_set_function(LCD_RST_PIN, FUNC_LCD_RST); sysctl_set_spi0_dvp_data(1); // fpioa映射 fpioa_set_function(PIN_UART_USB_RX, FUNC_UART_USB_RX); fpioa_set_function(PIN_UART_USB_TX, FUNC_UART_USB_TX); fpioa_set_function(PIN_UART_HMI_RX, FUNC_UART_HMI_RX); fpioa_set_function(PIN_UART_HMI_TX, FUNC_UART_HMI_TX); }static void io_set_power(void) { /* Set dvp and spi pin to 1.8V */ sysctl_set_power_mode(SYSCTL_POWER_BANK6, SYSCTL_POWER_V18); sysctl_set_power_mode(SYSCTL_POWER_BANK7, SYSCTL_POWER_V18); } void rgb888_to_lcd(uint8_t *src, uint16_t *dest, size_t width, size_t height) { size_t i, chn_size = width * height; for (size_t i = 0; i < width * height; i++) { uint8_t r = src[i]; uint8_t g = src[chn_size + i]; uint8_t b = src[chn_size * 2 + i]; uint16_t rgb = ((r & 0b11111000) << 8) | ((g & 0b11111100) << 3) | (b >> 3); size_t d_i = i % 2 ? (i - 1) : (i + 1); dest[d_i] = rgb; } } void lcd_ram_draw_rgb888(uint8_t *src, uint16_t *dest, size_t width, size_t height, size_t x_off, size_t y_off, size_t stride) { size_t x, y, chn_size = width * height; for (size_t y = 0; y < min(height, 240); y++) { for (size_t x = 0; x < width; x++) { size_t i = y * width + x; uint8_t r = src[i]; uint8_t g = src[chn_size + i]; uint8_t b = src[chn_size * 2 + i]; uint16_t rgb = ((r & 0b11111000) << 8) | ((g & 0b11111100) << 3) | (b >> 3); i = (y + y_off) * stride + x + x_off; size_t d_i = i % 2 ? (i - 1) : (i + 1); dest[d_i] = rgb; } } } int argmax(float* src, size_t count) { float max = FLT_MIN; size_t i, max_i = 0; for (i = 0; i < count; i++) { if (src[i] > max) { max = src[i]; max_i = i; } } return max_i; } //步进电机运动函数,因为电机的步距角不一样 void movestepper0(int seldir ,uint32_t mm0, int vms) //1mm----pul个脉冲 { uint64_t i; //和51单片机不一样,这个是GPIO_PV_HIGH代表高电平 gpio_pin_value_t valuetemp = GPIO_PV_HIGH; gpio_pin_value_t valuehigh = GPIO_PV_HIGH; gpio_pin_value_t valuelow = GPIO_PV_LOW; //判断方向 if(seldir==1) { valuetemp = GPIO_PV_HIGH; } else if(seldir==0) { valuetemp = GPIO_PV_LOW; } //设置方向 //用的是高速IO端口模式,所以是gpiohs gpiohs_set_pin(StepDir0_GPIONUM, valuetemp); //根据mm,计算脉冲数 for(i=0;i<mm0*xmmpul;i++) { gpiohs_set_pin(StepPul0_GPIONUM, valuehigh); msleep(vms);// gpiohs_set_pin(StepPul0_GPIONUM, valuelow); msleep(vms);// } } //************************************************************************************* void UART_SendHMI_Byte(char mydata) // 发送一个字节 { uart_send_data(UART_HMI_NUM, &mydata, 1); } //************************************************************************************* void UART_SendHMI_Str(char *s) //发送文本串 { int i=0; while(s[i]!=0) { UART_SendHMI_Byte(s[i]); i++; } } //************************************************************************************* void UART_SendHMI_END(void) //发送结束符 { UART_SendHMI_Byte(0xFF); UART_SendHMI_Byte(0xFF); UART_SendHMI_Byte(0xFF); } //************************************************************************************* /** * Function main * @author Gengyue * @date 2020.05.27 * @brief 主函数,程序的入口 * @param[in] void * @param[out] void * @retval 0 * @par History 无 */ int main(void) { int i=0; hardware_init();// 硬件引脚初始化 /* Set CPU and dvp clk */ sysctl_pll_set_freq(SYSCTL_PLL0, 800000000UL); sysctl_pll_set_freq(SYSCTL_PLL1, 400000000UL); sysctl_pll_set_freq(SYSCTL_PLL2, 45158400UL); sysctl_clock_enable(SYSCTL_CLOCK_AI); plic_init(); io_set_power(); gpio_init(); // 使能GPIO的时钟 // 设置LED0和LED1的GPIO模式为输出 gpio_set_drive_mode(LED0_GPIONUM, GPIO_DM_OUTPUT); gpio_set_drive_mode(LED1_GPIONUM, GPIO_DM_OUTPUT); // 先关闭LED0和LED1 gpio_pin_value_t value = GPIO_PV_HIGH; gpio_set_pin(LED0_GPIONUM, value); gpio_set_pin(LED1_GPIONUM, value); // 设置垃圾桶的传感器的GPIO模式为上拉输入 gpiohs_set_drive_mode(LJT0_GPIONUM, GPIO_DM_INPUT_PULL_UP); gpiohs_set_drive_mode(LJT1_GPIONUM, GPIO_DM_INPUT_PULL_UP); gpiohs_set_drive_mode(LJT2_GPIONUM, GPIO_DM_INPUT_PULL_UP); gpiohs_set_drive_mode(LJT3_GPIONUM, GPIO_DM_INPUT_PULL_UP); gpiohs_set_drive_mode(LJT4_GPIONUM, GPIO_DM_INPUT_PULL_UP); gpiohs_set_drive_mode(LJT5_GPIONUM, GPIO_DM_INPUT_PULL_UP); //设置步进电机的方向和脉冲引脚是输出模式 gpiohs_set_drive_mode(StepDir0_GPIONUM, GPIO_DM_OUTPUT); gpiohs_set_drive_mode(StepPul0_GPIONUM, GPIO_DM_OUTPUT); gpiohs_set_drive_mode(StepDir1_GPIONUM, GPIO_DM_OUTPUT); gpiohs_set_drive_mode(StepPul1_GPIONUM, GPIO_DM_OUTPUT); uart_init(UART_USB_NUM); uart_configure(UART_USB_NUM, 115200, UART_BITWIDTH_8BIT, UART_STOP_1, UART_PARITY_NONE); uart_init(UART_HMI_NUM); uart_configure(UART_HMI_NUM, 9600, UART_BITWIDTH_8BIT, UART_STOP_1, UART_PARITY_NONE); /* 开机发送hello yahboom! */ char *hello = {"hello yahboom!\n"}; uart_send_data(UART_USB_NUM, hello, strlen(hello)); /* LCD init */ printf("LCD init\n"); lcd_init(); lcd_set_direction(DIR_YX_LRUD); lcd_clear(BLACK); // lcd_draw_picture_half(0, 0, 320, 240, logo); lcd_draw_string(70, 40, "Hello uuyyttr!", RED); lcd_draw_string(70, 60, "c", BLUE); //lcd_draw_char(70,80,'o',RED);//lcd_draw_char(x, y, *str, color); sleep(1); /* DVP init */ printf("DVP init\n"); dvp_init(8); dvp_set_xclk_rate(24000000); dvp_enable_burst(); dvp_set_output_enable(0, 1); dvp_set_output_enable(1, 1); dvp_set_image_format(DVP_CFG_RGB_FORMAT); dvp_set_image_size(320, 240); ov2640_init(); kpu_image.pixel = 3; kpu_image.width = 320; kpu_image.height = 240; image_init(&kpu_image); display_image.pixel = 2; //2->3 LIUSEN display_image.width = 320; display_image.height = 240; image_init(&display_image); crop_image.pixel = 3; crop_image.width = 224; crop_image.height = 224; image_init(&crop_image); //存放AI图像的地址,供AI模块进行算法处理(红色、绿色、蓝色/分量地址) dvp_set_ai_addr((uint32_t)kpu_image.addr, (uint32_t)(kpu_image.addr + 320 * 240), (uint32_t)(kpu_image.addr + 320 * 240 * 2)); //设置采集图像在内存中的存放地址,可以用来显示 dvp_set_display_addr((uint32_t)display_image.addr); //图像开始采集中断| 图像结束采集中断 dvp_config_interrupt(DVP_CFG_START_INT_ENABLE | DVP_CFG_FINISH_INT_ENABLE, 0); //禁用自动接收图像模式 dvp_disable_auto(); /* DVP interrupt config */ printf("DVP interrupt config\n"); plic_set_priority(IRQN_DVP_INTERRUPT, 1); //设置中断优先级 plic_irq_register(IRQN_DVP_INTERRUPT, dvp_irq, NULL); //注册外部中断函数 plic_irq_enable(IRQN_DVP_INTERRUPT); //使能外部中断 char recv = 0; unsigned char HMICmd[50]="pic"; // lcd_draw_char(10,0,'g',RED); while (1) { //查询几个GPIO垃圾桶,返回传感器..参考keypad的案例代码 gpio_pin_value_t state_LJT0 = gpiohs_get_pin(LJT0_GPIONUM); gpio_pin_value_t state_LJT1 = gpiohs_get_pin(LJT1_GPIONUM); gpio_pin_value_t state_LJT2 = gpiohs_get_pin(LJT2_GPIONUM); gpio_pin_value_t state_LJT3 = gpiohs_get_pin(LJT3_GPIONUM); gpio_pin_value_t state_LJT4 = gpiohs_get_pin(LJT4_GPIONUM); gpio_pin_value_t state_LJT5 = gpiohs_get_pin(LJT5_GPIONUM); //gpio_pin_value_t value = GPIO_PV_HIGH; GPIO_PV_LOW //LED 低电平亮,高电平不亮 if(!state_LJT0) { // gpio_set_pin(LED0_GPIONUM, GPIO_PV_LOW); gpio_set_pin(LED1_GPIONUM, GPIO_PV_LOW); } if(!state_LJT1) { // gpio_set_pin(LED0_GPIONUM, GPIO_PV_LOW); gpio_set_pin(LED1_GPIONUM, GPIO_PV_HIGH); } if(!state_LJT2) { //gpio_set_pin(LED0_GPIONUM, GPIO_PV_HIGH); gpio_set_pin(LED1_GPIONUM, GPIO_PV_LOW); } if(!state_LJT3) { // gpio_set_pin(LED0_GPIONUM, GPIO_PV_HIGH); gpio_set_pin(LED1_GPIONUM, GPIO_PV_HIGH); } // //步进电机测试,正方向,两个电机都走100000个脉冲 // gpiohs_set_pin(StepDir0_GPIONUM, GPIO_PV_HIGH); // gpiohs_set_pin(StepDir1_GPIONUM, GPIO_PV_HIGH); // for(i=0;i<100000;i++) // { // gpiohs_set_pin(StepPul0_GPIONUM, GPIO_PV_HIGH); // gpiohs_set_pin(StepPul1_GPIONUM, GPIO_PV_HIGH); // msleep(1);//5000 // gpiohs_set_pin(StepPul0_GPIONUM, GPIO_PV_LOW); // gpiohs_set_pin(StepPul1_GPIONUM, GPIO_PV_LOW); // msleep(1);//5000 // } // sleep(10); // //步进电机测试,反方向,两个电机都走100000个脉冲 // gpiohs_set_pin(StepDir0_GPIONUM, GPIO_PV_LOW); // gpiohs_set_pin(StepDir1_GPIONUM, GPIO_PV_LOW); // //步进电机测试,正方向,两个电机都走100000个脉冲 // for(i=0;i<100000;i++) // { // gpiohs_set_pin(StepPul0_GPIONUM, GPIO_PV_HIGH); // gpiohs_set_pin(StepPul1_GPIONUM, GPIO_PV_HIGH); // msleep(1);//5000 // gpiohs_set_pin(StepPul0_GPIONUM, GPIO_PV_LOW); // gpiohs_set_pin(StepPul1_GPIONUM, GPIO_PV_LOW); // msleep(1);//5000 // } // sleep(10); // movestepper0(0,100,1); //0方向,100个mm,速度是1ms // sleep(10); // movestepper0(1,100,1); //0方向,100个mm,速度是1ms // sleep(10); // g_dvp_finish_flag = 0; // dvp_clear_interrupt(DVP_STS_FRAME_START | DVP_STS_FRAME_FINISH); // dvp_config_interrupt(DVP_CFG_START_INT_ENABLE | DVP_CFG_FINISH_INT_ENABLE, 1); // while (g_dvp_finish_flag == 0) // ; // image_crop(&kpu_image, &crop_image, 48, 8); // g_ai_done_flag = 0; printf("A\n"); /* 等待串口信息,并通过串口发送出去 */ if(uart_receive_data(UART_USB_NUM, &recv, 1)) { uart_send_data(UART_USB_NUM, &recv, 1); } printf("B\n"); /* 等待串口信息,并通过串口发送出去 */ while(1) { state_LJT0 = gpiohs_get_pin(LJT0_GPIONUM); state_LJT1 = gpiohs_get_pin(LJT1_GPIONUM); if(!state_LJT0) //IO18 { // UART_SendHMI_Str(char *s); UART_SendHMI_Str("C.b8.bco=63488"); //变红色 UART_SendHMI_END(); gpio_set_pin(LED1_GPIONUM, GPIO_PV_LOW); } if(!state_LJT1) //IO18 { // UART_SendHMI_Str(char *s); UART_SendHMI_Str("C.b8.bco=2014"); //变红色 UART_SendHMI_END(); gpio_set_pin(LED1_GPIONUM, GPIO_PV_LOW); } if(uart_receive_data(UART_HMI_NUM, &recv, 1))//串口接收,应该放在中断 { printf("C\n"); lcd_clear(BLACK); lcd_draw_char(70,80,recv+0x30,BLUE); printf("D\n"); } } } return 0; }
pin_config.h
/** * @par Copyright (C): 2016-2022, Shenzhen Yahboom Tech * @file pin_config.c * @author Gengyue * @version V1.0 * @date 2020.05.27 * @brief 硬件引脚与软件GPIO的宏定义 * @details * @par History 见如下说明 * * version: 由于K210使用fpioa现场可编程IO阵列,允许用户将255个内部功能映射到芯片外围的48个自由IO上 * 所以把硬件IO和软件GPIO功能抽出来单独设置,这样更容易理解。 */ #ifndef _PIN_CONFIG_H_ #define _PIN_CONFIG_H_ /*****************************HEAR-FILE************************************/ #include "fpioa.h" #include "uart.h" /*****************************HARDWARE-PIN*********************************/ // 硬件IO口,与原理图对应 #define PIN_LED_0 (0) //LED灯 #define PIN_LED_1 (17) #define PIN_LJT_0 (18) //垃圾桶LJT #define PIN_LJT_1 (19) #define PIN_LJT_2 (20) #define PIN_LJT_3 (21) #define PIN_LJT_4 (22) #define PIN_LJT_5 (23) #define PIN_DIR_0 (1) //传送步进电机0方向 IO12是普通IO #define PIN_PUL_0 (2) //传送步进电机0脉冲输出 普通IO #define PIN_DIR_1 (3) //传送步进电机1方向 #define PIN_PUL_1 (16) //传送步进电机1脉冲输出 #define PIN_UART_USB_RX (4) #define PIN_UART_USB_TX (5) #define PIN_UART_HMI_RX (13) #define PIN_UART_HMI_TX (14) /*****************************SOFTWARE-GPIO********************************/ // 软件GPIO口,与程序对应 #define LED0_GPIONUM (0) #define LED1_GPIONUM (1) #define LJT0_GPIONUM (2) #define LJT1_GPIONUM (3) #define LJT2_GPIONUM (4) #define LJT3_GPIONUM (5) #define LJT4_GPIONUM (6) #define LJT5_GPIONUM (7) #define StepDir0_GPIONUM (8) #define StepPul0_GPIONUM (9) #define StepDir1_GPIONUM (10) #define StepPul1_GPIONUM (11) #define UART_USB_NUM UART_DEVICE_3 #define UART_HMI_NUM UART_DEVICE_1 /*****************************FUNC-GPIO************************************/ // GPIO口的功能,绑定到硬件IO口 #define FUNC_LED0 (FUNC_GPIO0 + LED0_GPIONUM) #define FUNC_LED1 (FUNC_GPIO0 + LED1_GPIONUM) //IO口18--23对应HS高速口,看芯片手册的引脚定义表 #define FUNC_LJT0 (FUNC_GPIOHS0 + LJT0_GPIONUM) #define FUNC_LJT1 (FUNC_GPIOHS0 + LJT1_GPIONUM) #define FUNC_LJT2 (FUNC_GPIOHS0 + LJT2_GPIONUM) #define FUNC_LJT3 (FUNC_GPIOHS0 + LJT3_GPIONUM) #define FUNC_LJT4 (FUNC_GPIOHS0 + LJT4_GPIONUM) #define FUNC_LJT5 (FUNC_GPIOHS0 + LJT5_GPIONUM) #define FUNC_DIR0 (FUNC_GPIOHS0 + StepDir0_GPIONUM) #define FUNC_PUL0 (FUNC_GPIOHS0 + StepPul0_GPIONUM) #define FUNC_DIR1 (FUNC_GPIOHS0 + StepDir1_GPIONUM) #define FUNC_PUL1 (FUNC_GPIOHS0 + StepPul1_GPIONUM) #define FUNC_UART_USB_RX (FUNC_UART1_RX + UART_USB_NUM * 2) #define FUNC_UART_USB_TX (FUNC_UART1_TX + UART_USB_NUM * 2) #define FUNC_UART_HMI_RX (FUNC_UART1_RX + UART_HMI_NUM * 2) #define FUNC_UART_HMI_TX (FUNC_UART1_TX + UART_HMI_NUM * 2) #endif /* _PIN_CONFIG_H_ */
更多相关内容 -
S7-1500与HMI通信方法(手把手教学,强烈推荐)
2021-02-04 22:34:26S7-1500与HMI通信方法(手把手教学,强烈推荐) -
博途S7-1500CPu与HMI通信例程.rar
2021-03-30 10:47:08介绍博途S7-1500CPu与HMI通信 -
通过HMI通信的水泵站自动化控制系统
2021-03-16 02:56:56通过HMI通信的水泵站自动化控制系统.pdf 介绍了关于通过HMI通信的水泵站自动化控制系统的详细说明,提供人机界面的技术资料的下载。 -
欧姆龙NJ网络实验,NJ与HMI通信.pdf
2021-04-07 22:56:59欧姆龙NJ网络实验,NJ与HMI通信 -
STM32 与陶晶驰hmi通信.rar
2019-08-03 14:22:03此文件夹含stm32与陶晶驰串口屏通信工程及工程实例 -
通过HMI通信的水泵站自动化控制系统.pdf
2019-10-09 21:05:45通过HMI通信的水泵站自动化控制系统pdf,通过HMI通信的水泵站自动化控制系统 -
Cimplicity HMI 通信设置手册(官方英文)
2014-11-19 11:10:13Cimplicity HMI 通信设置手册(官方英文)。 -
单片机通过Modbus协议与HMI通信
2011-10-05 15:46:44ModBus通讯协议分为RTU协议和ASCII协议 -
无锡北辰S7通信模块HMI-S71200通信使用手册V1.3.pdf
2021-09-02 10:50:34无锡北辰S7通信模块HMI-S71200通信使用手册 -
威纶通HMI做Modbus网关 C#通过网络采集数据.zip
2020-05-13 09:35:11这是我实际在上海做的一个项目当时车间有20多台设备,我采用了该方式可以很快的采集到设备的数据,现在分享给大家一同学习学习,如若有不足之处望各位指教,大家互相学习学习! -
PLC与步科HMI通信连接(RS232)
2022-05-06 10:16:52PLC与步科HMI通信连接_RS232型号选择硬件接口说明PLC主HMI从HMI主PLC从 型号选择 HMI型号 软件 步科MT4532TE Kinco HMIware 2.5 控制器型号 软件 中型PLC(以PMC600为例) Codesys 硬件接口说明...型号选择
HMI型号 软件 步科MT4532TE Kinco HMIware 2.5 控制器型号 软件 中型PLC(以PMC600为例) Codesys 硬件接口说明
PMC610 MT8102iE PLC主HMI从
PLC:
Step1:新建工程
Step2:添加RS232 Modbus主站
Step3:配置串口参数,波特率9600,偶校验,数据位8,停止位1
Step4:添加通讯设置,读写寄存器
Step5:下载工程进PLCHMI:
Step1:新建工程,拖出对应HMI型号MT4532TE。配置IP地址,和串口
Step2:拖出PLC中的Modbus RTU Slave,并通讯串口连接
Step3:右侧工程选择HMI0.在PLC元件中添加数值显示和数值输入
Step4:下载工程进HMI(需要先选择下载方式,选择IP)HMI主PLC从
PLC:
Step1:新建工程
Step2:选择Modbus从站
Step3:配置串口参数,波特率9600,偶校验,数据位8,停止位1,站号1
Step4:程序添加DWS全局变量。
Step5:下载工程进PLCHMI:
Step1:新建工程,拖出对应HMI型号MT4532TE。配置IP地址,和串口0.
Step2:拖出PLC中的Modbus RTU,并通讯串口连接
Step3:右侧工程选择HMI0.在PLC元件中添加数值显示和数值输入
Step4:下载工程进HMI(需要先选择下载方式,选择IP)
-
STM32F103 485通信开发实例(二):与HMI建立初步通信
2022-04-11 17:38:56与威纶通触摸屏建立初步通信,主要包含触摸屏的具体配置过程,以及样机测试结果上一篇文章研究了两个stm32芯片之间如何利用485进行数据交互,本文在此基础上,进一步研究stm32如何与嵌入式触摸屏建立通信联系。选取威纶通TK6071iP作为主机,通过其COM2上的RS-485接口,与作为从机的一块TM32F103开发板连接。
主机与从机之间的485通信线路采用半双工形式,威纶通TK6071iP触摸屏配置采用Modbus RTU通信规约。作为从机,stm32开发板需要开发相应的Modbus RTU协议。本文首先直接采用上一篇文章中的基本程序,尝试接收上位机基于Modbus RTU通信规约发送的数据,分析数据发送机制的特点,为后续开发下位机的协议做铺垫。
一、威纶通触摸屏配置
建立基本工程,用相应元件搭建指令/数据发送界面,进行相应配置。搭建过程可直接参考威纶通官方例程,几个主要的配置过程如下:
1、系统参数设置
2、元件设置
首先采用多状态设置元件,然后采用数值元件,分别测试两种常用元件能不能将数据发送到从机上。
二、通信测试
1、多状态设置元件
从机接收中断代码:
void USART2_IRQHandler(void) { u8 readd; u8 error; u8 check_temp = 0; u8 i; if(USART_GetITStatus(USART2,USART_IT_RXNE)!=RESET) { //检测噪音、帧错误或校验错误 if(USART_GetFlagStatus(USART2,USART_FLAG_NE|USART_FLAG_FE|USART_FLAG_PE)) { error = 1; } else { error = 0; } //读取接收字节 readd = USART_ReceiveData(USART2); //逐个读取各字节 if((RS485_RX_CNT < 8)&&(error == 0)) { RS485_RX_BUFF[RS485_RX_CNT]=res; RS485_RX_CNT++; } //8字节读取完毕,进行数据整理,及返回数据发送 if(RS485_RX_CNT == 8) { RS485_RX_CNT = 0; //首先进行数据校验 for(i=0;i<7;i++) { check_temp += RS485_RX_BUFF[i]; } //若校验通过,返回一组数据 if(check_temp == RS485_RX_BUFF[7]) { //组织返回数据 RS485_TX_BUFF[0] = 0x10; RS485_TX_BUFF[1] = 0x10; RS485_TX_BUFF[2] = 0x10; RS485_TX_BUFF[3] = 0x10; RS485_TX_BUFF[4] = 0x10; RS485_TX_BUFF[5] = 0x10; RS485_TX_BUFF[6] = 0x10; //生成返回数据的校验值 RS485_TX_BUFF[7] = 0x00; for(i=0;i<7;i++) { RS485_TX_BUFF[7] += RS485_TX_BUFF[i]; } //数据发送 RS485_RN = 1; RS485_Send(RS485_TX_BUFF,8); RS485_RN = 0; } //若校验不通过,返回另一组数据 else { //组织返回数据 RS485_TX_BUFF[0] = 0x11; RS485_TX_BUFF[1] = 0x00; RS485_TX_BUFF[2] = 0x00; RS485_TX_BUFF[3] = 0x00; RS485_TX_BUFF[4] = 0x00; RS485_TX_BUFF[5] = 0x00; RS485_TX_BUFF[6] = 0x00; //生成返回数据的校验值 RS485_TX_BUFF[7] = 0x00; for(i=0;i<7;i++) { RS485_TX_BUFF[7] += RS485_TX_BUFF[i]; } //数据发送 RS485_RN = 1; RS485_Send(RS485_TX_BUFF,8); RS485_RN = 0; } } } }
从机收到的指令如下图,对比发现其与主机发送的格式一致。所以多状态设置元件的指令可以直接被从机接收。
2、数值元件
采用数值元件,触摸屏上电初始化之后,发数据之前会报错,入下图所示:
经初步测试,根据从机得到的指令进行分析,个人认为出现错误的原因可能是由于数值元件在触摸屏上电之后,在正式发数据之前,需要与从机进行初步的通信,以确认连接通畅。此时由于从机中尚无相应的Modbus规约,无法相应来自于数值元件的通信请求,主机反复多次发送请求却得不到响应,最终导致触摸屏做出装置无响应的判断。
三、结论
为了实现与HMI之间的完整通信,需在stm32中引入Modbus RTU通信规约,过程中需对HMI的数据发送和接收机制进行深入的测试,才能更好地实现高质量的数据交互。
-
DS1302时钟模块介绍及与USRAT HMI通信
2018-10-12 18:55:48一、DS1302时钟模块 现在流行的串行时钟电路很多,如DS1302、 DS1307、PCF8485等。这些电路的接口简单、价格低廉、使用方便,被广泛地采用。...采用三线接口与CPU进行同步通信,并可采用突发方式一次传送...一、DS1302时钟模块
现在流行的串行时钟电路很多,如DS1302、 DS1307、PCF8485等。这些电路的接口简单、价格低廉、使用方便,被广泛地采用。
DS1302 是美国DALLAS公司推出的一种高性能、低功耗、带RAM的实时时钟电路,它可以对年、月、日、周、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.0V~5.5V。采用三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM数据。DS1302内部有一个31×8的用于临时性存放数据的RAM寄存器。DS1302是DS1202的升级产品,与DS1202兼容,但增加了主电源/后备电源双电源引脚,同时提供了对后备电源进行涓细电流充电的能力,该芯片采用普通32.768kHz晶振,DS1302 工作时功耗很低保持数据和时钟信息时功率小于1mW。
图1 DS1302时钟模块实物图
图2 DS1302时钟模块封装
表1 DS1302芯片引脚功能介绍表
VCC1
后备电源
GND
电源地
VCC2
工作电源
X1
晶振32.768kHz输入
X2
SCLK
时钟信号
I/O
数据输入输出
RST
复位信号|片选信号
DS1302时钟模块的引脚功能介绍如表1所示,而时序不再做陈述,需要再自行查找资料。
二、DS1302时钟模块驱动代码
1.头文件
#ifndef _DS1302_H_ #define _DS1302_H_ #include "STC15F2K60S2.h" #ifndef UINT8 #define UINT8 unsigned char #endif #ifndef DS1302_READ_BURST #define DS1302_READ_BURST 0xBF #endif #ifndef DS1302_WRITE_BURST #define DS1302_WRITE_BURST 0xBE #endif sbit DS1302_IO = P1^4; sbit DS1302_RST = P1^5; sbit DS1302_SCLK = P1^3; extern UINT8 xdata time[9]; extern UINT8 xdata date[11]; extern UINT8 xdata current_day[2]; //声明全局变量 void DS1302_WriteByte(UINT8 data_byte);//向ds1302写一个字节 void DS1302_ReadByte(UINT8 *data_byte);//从ds1302读一个字节 void DS1302_Start();//操作起始信号 void DS1302_Over();//操作结束信号 void DS1302_ClearWriteProtection();//清除写保护 void DS1302_SetWriteProtection();//设置写保护 void DS1302_SetTime(UINT8 *ds1302_set_buffer);//设置ds1302的时间 void DS1302_ReadTime(UINT8 *ds1302_build_buffer);//读取ds1302的时间 void Time_Build();//系统从ds1302读取时间 void Time_Set();//系统向ds1302设置时间 void Time_Init();//系统时间初始化 #endif
2.主程序
#include "ds1302.h" void DS1302_WriteByte(UINT8 data_byte)//向ds1302写一个字节 { UINT8 i; for (i=0;i<8;i++) { DS1302_IO = data_byte & 0x01; DS1302_SCLK = 1; data_byte >>= 1; DS1302_SCLK = 0; } } void DS1302_ReadByte(UINT8 *data_byte) //从ds1302读一个字节 { UINT8 i; for (i=0;i<8;i++) { *data_byte >>= 1; if (DS1302_IO){*data_byte |= 0x80;} DS1302_SCLK = 1; DS1302_SCLK = 0; } } void DS1302_Start()//操作起始信号 { DS1302_RST = 0; DS1302_SCLK = 0; DS1302_RST = 1; } void DS1302_Over()//操作结束信号 { DS1302_IO = 0; DS1302_RST = 0; } void DS1302_ClearWriteProtection()//清除写保护 { DS1302_Start(); DS1302_WriteByte(0x8E); DS1302_WriteByte(0x00); DS1302_Over(); } void DS1302_SetWriteProtection()//设置写保护 { DS1302_Start(); DS1302_WriteByte(0x8E); DS1302_WriteByte(0x80); DS1302_Over(); } void DS1302_SetTime(UINT8 *ds1302_set_buffer)//突发模式下设置时间 { UINT8 i; DS1302_ClearWriteProtection(); DS1302_Start(); DS1302_WriteByte(DS1302_WRITE_BURST); for (i=0; i<7; i++) { DS1302_WriteByte(ds1302_set_buffer[i]); } DS1302_WriteByte(0x80);//突发模式一次要写8个字节,第八个字节是写保护字节 DS1302_Over(); } void DS1302_ReadTime(UINT8 *ds1302_read_buffer)//突发模式下读取时间 { UINT8 i,Temp; DS1302_ClearWriteProtection(); DS1302_Start(); DS1302_WriteByte(DS1302_READ_BURST); for (i=0; i<7; i++) { DS1302_ReadByte(ds1302_read_buffer+i); } DS1302_ReadByte(&Temp);//突发模式一次读8个字节,最后一字节读出来没用 DS1302_Over(); DS1302_SetWriteProtection(); } void Time_Build()//读取时间后转换成需要的格式 { UINT8 xdata ds1302_build_buffer[7]; DS1302_ReadTime(ds1302_build_buffer); time[7] = (ds1302_build_buffer[0]&0x0f)+'0'; time[6] = ((ds1302_build_buffer[0]&0x70)>>4)+'0'; time[4] = (ds1302_build_buffer[1]&0x0f)+'0'; time[3] = ((ds1302_build_buffer[1]&0x70)>>4)+'0'; time[1] = (ds1302_build_buffer[2]&0x0f)+'0'; time[0] = ((ds1302_build_buffer[2]&0x30)>>4)+'0'; date[9] = (ds1302_build_buffer[3]&0x0f)+'0'; date[8] = ((ds1302_build_buffer[3]&0x30)>>4)+'0'; date[6] = (ds1302_build_buffer[4]&0x0f)+'0'; date[5] = ((ds1302_build_buffer[4]&0x10)>>4)+'0'; date[3] = (ds1302_build_buffer[6]&0x0f)+'0'; date[2] = ((ds1302_build_buffer[6]&0xf0)>>4)+'0'; } void Time_Set()//将时间转化为对应格式存入ds1302 { UINT8 xdata ds1302_set_buffer[7]; ds1302_set_buffer[0] = time[7]-'0'; ds1302_set_buffer[0] |= ((time[6]-'0')&0x07)<<4; ds1302_set_buffer[1] = time[4]-'0'; ds1302_set_buffer[1] |= ((time[3]-'0')&0x07)<<4; ds1302_set_buffer[2] = time[1]-'0'; ds1302_set_buffer[2] |= ((time[0]-'0')&0x03)<<4; ds1302_set_buffer[3] = date[9]-'0'; ds1302_set_buffer[3] |= ((date[8]-'0')&0x03)<<4; ds1302_set_buffer[4] = date[6]-'0'; ds1302_set_buffer[4] |= ((date[5]-'0')&0x01)<<4; ds1302_set_buffer[6] = date[3]-'0'; ds1302_set_buffer[6] |= ((date[2]-'0')&0x0f)<<4; ds1302_set_buffer[5] = 0x01; DS1302_SetTime(ds1302_set_buffer); } void Time_Init()//开机时间初始化 { Time_Build(); current_day[0] = date[8]; current_day[1] = date[9];//保存当前日期,用于检测日期变化 }
三、DS1302时钟模块与USRAT HMI通信
uchar a=0,b=0,c=0,d=0,e=0,f=0; /**********显示时间**********/ a = date[2]; //发送年数据 b = date[3]; c = date[5]; //发送月数据 d = date[6]; e = date[8]; //发送日数据 f = date[9]; write_txt("t0.txt="); //发送文本 write_COM(34); //双引号 write_COM(a); write_COM(b); write_COM(34); write_END(); //结束符 write_txt("t1.txt="); //发送文本 write_COM(34); //双引号 write_COM(c); write_COM(d); write_COM(34); write_END(); //结束符 write_txt("t2.txt="); //发送文本 write_COM(34); //双引号 write_COM(e); write_COM(f); write_COM(34); write_END(); //结束符 a = time[0]; //发送时数据 b = time[1]; c = time[3]; //发送分钟数据 d = time[4]; e = time[6]; //发送秒钟数据 f = time[7]; write_txt("t3.txt="); //发送文本 write_COM(34); //双引号 write_COM(a); write_COM(b); write_COM(34); write_END(); //结束符 write_txt("t4.txt="); //发送文本 write_COM(34); //双引号 write_COM(c); write_COM(d); write_COM(34); write_END(); //结束符 write_txt("t5.txt="); //发送文本 write_COM(34); //双引号 write_COM(e); write_COM(f); write_COM(34); write_END(); //结束符 write_txt("t9.txt="); //发送文本 write_COM(34); if(week==1) //发送星期数据 write_txt("一"); if(week==2) write_txt("二"); if(week==3) write_txt("三"); if(week==4) write_txt("四"); if(week==5) write_txt("五"); if(week==6) write_txt("六"); if(week==7) write_txt("日"); write_COM(34); write_END();
-
DS18B20温度传感器模块介绍及与USART HMI通信
2018-10-11 20:51:50(2)单片机串口通信部分程序 ①头文件 #ifndef _UART_H_ #define _UART_H_ #include #ifndef uchar #define uchar unsigned char #endif #ifndef uint #define uint unsigned int #endif ... -
如何用单片机通过MODBUS协议与HMI通信
2011-03-22 18:20:53Modbus协议最初由Modicon公司开发出来,在1979年末该公司成为施耐德自动化(SchneiderAutomation)部门的一部分,现在Modbus已经是工业领域全球最流行的协议。此协议支持传统的RS-232、RS-422、RS-485和以太网设备。... -
TIA Portal如何设置实现PLC与HMI仿真通讯功能
2018-02-08 08:27:01最近一直有接到客户关于使用TIA Portal实现程序仿真遇到问题的案例,绝大部分问题都集中在无法实现PLC与HMI的仿真通讯,在解决了客户问题的同时,我也把各种设置的可能总结了一下,供大家实际操作时参考。 -
陶晶池 USART HMI串口屏通信详解.7z
2020-03-07 12:30:00该资源包含了除网络上陶晶池串口屏上位机调试视频和一些文档之外,还有一个我自己写的STM32F103的通信程序,以及一个说明文档。该文档详细说明了STM32F1是如何给串口屏发送数据的 -
HMI与STM32通信
2019-08-11 09:07:54这是电赛的准备程序,可以用于STM32与HMI串口屏进行通信,请大家认真参考!!! -
STM32和HMI串口屏通信的使用教程
2019-10-24 23:28:23USART HMI 视频教程:HMI基础视频教程 本人博客下载页面里也有参考代码: stm32代码 :https://download.csdn.net/download/qq_40987215/11643433 HMI代码:... -
无锡北辰通过BCNet通信模块实现欧姆龙PLC与HMI的数据点表探测.pdf
2021-09-02 11:07:23无锡北辰通过BCNet通信模块实现欧姆龙PLC与HMI的数据点表探测 -
TIA博途中如何用一块HMI触摸屏同时连接两个不同网段的PLC进行通信?.docx
2021-11-26 08:26:49TIA博途中如何用一块HMI触摸屏同时连接两个不同网段的PLC进行通信? -
TIA博途中如何减少HMI上BOOL型变量的使用以减轻与PLC的通信负载?.docx
2021-05-14 16:21:40TIA博途中如何减少HMI上BOOL型变量的使用以减轻与PLC的通信负载? -
完整版 HMI串口屏幕stm32通信.zip
2019-12-24 17:13:00亲测好用,挺不错的资源,大家快来下载吧!挺有用的!需要的话可以来下载哦!HMI串口屏和stm32f103双机通信的方法和例子,内带了说明 -
TIA博途中如何用一块HMI触摸屏同时连接两个不同网段的PLC进行通信?
2021-11-27 08:31:05TIA博途中如何用一块HMI触摸屏同时连接两个不同网段的PLC进行通信? 大家都知道,HMI如果要和PLC进行以太网通信的话,需要将二者的IP地址设置在同一网段内,这样才可以正常建立通信连接。 如下图所示:PLC1的IP地址... -
陶晶池 USART HMI 串口屏与STM32F1通信详解
2018-07-19 19:31:29该资源包含了除网络上陶晶池串口屏上位机调试视频和一些文档之外,还有一个我自己写的STM32F103的通信程序,以及一个说明文档。该文档详细说明了STM32F1是如何给串口屏发送数据的 -
显控HMI 与 PLC 通信报错数字提示.pdf
2020-10-19 17:20:14显控HMI与PLC通信时出现的报错数字信息说明。可能错误的原因有:检验错误、数据长度不对、无数据返回。 -
串口显示屏HMI与stm32相互通信,点亮小灯
2018-03-27 11:00:29HMI串口显示屏与单片机STM32通信,在触摸屏上可以点亮led灯,也可以在程序发送相关指令控制串口显示屏。 -
如何实现HMI控制S120时的通信状态监视
2021-03-19 23:27:17介绍了关于如何实现HMI控制S120时的通信状态监视的详细说明,提供运动控制器的技术资料的下载。