Hôm nay mình giới thiệu các bạn chạy Arduino với màn hình HMI delta
Đầu tiên các bạn cài đặt phần mền HMI delta bản mới nhất
Đầu tiên chúng ta tìm hiểu khung truyền modbus
.Phần cứng HMI mosbus để chống nhiễu và cách ly GND dùng ADUM3251 hoặc ADUM1201 kết hợp MAX3232IDR thêm nguồn ISO IB0505
1.Khung truyền modbus
2.Các địa chỉ modbus
01 READ COIL STATUS
02 READ INPUT STATUS
03 READ HOLDING REGISTERS
04 READ INPUT REGISTERS
05 WRITE SINGLE COIL
06 WRITE SINGLE REGISTER
15 WRITE MULTIPLE COILS
16 WRITE MULTIPLE REGISTERS
địa chỉ :0000-9999 một thiết bị master có thể đọc và ghi địa chỉ này
địa chỉ :1000-19999 digital Input
địa chỉ :3000-39999 analog Input
địa chỉ :4000-49999 analog output
Các bạn tham khảo thêm trang chủ modbus :https://www.modbustools.com/modbus.html
ở đây chúng ta quan tâm đến hàm 01 :01 READ COIL STATUS như đọc các trạng thái nút bấm ,led hiển thị
Hàm :03 READ HOLDING REGISTERS Ghi giá trị vào thanh ghi 16bit để hiển thị các giá trị số đếm
Hàm:04 READ INPUT REGISTERS vừa ghi vừa đọc được giá trị ,để nhận giữ liệu HMi
Tiếp theo chúng ta đển màn hình HMI
Giao diện đơn giản dùng HMI delta
Như vậy song quá trình Cài đặt HMI ,nếu không có màn hình chúng ta có thể chạy online HMI với Arduino qua USB to com
Đối với mạch thực tế cần qua MAX3232IDR hoặc ADUM3251 iso
Code STM32F4 :
Hàm check CRC
#include <crc_modbus.h>
void crc(unsigned char *pBuffer, unsigned char usBufferSize)
{
unsigned int usResult = 0xFFFF;
unsigned char j;
unsigned char i;
for(j = 0; j < usBufferSize; j++)
{
usResult = usResult ^ pBuffer[j];
for(i = 0; i < 8; i++)
{
if(usResult & 0x01)
{
usResult >>= 1;
usResult = usResult ^ 0xA001;
}
else usResult >>= 1;
}
}
CRCLo = (char) usResult;
CRCHi = (char)(usResult>>8);
}
//
Hàm đọc ghi dữ liệu
#include "stm32f4xx.h"
#include <crc_modbus.h>
extern uint8_t _msg[100];
extern void putchar1(u8 ch);
int i;
void write_data_slave_F1(uint8_t id,uint8_t fuction,uint16_t value_add,uint16_t value_cnt,uint8_t _len,uint16_t time)
{
_msg[0]=id&0xFF;//id
_msg[1]=fuction&0xFF;//idfuction
_msg[2]= value_add>>8;
_msg[3]= value_add&0xFF;
_msg[4]= value_cnt>>8;
_msg[5]= value_cnt&0xFF;
crc(_msg,_len-2);
_msg[6]=CRCLo ;
_msg[7]=CRCHi ;
for(i=0;i<_len;i++)
{
putchar1(_msg[i]);
}
// HAL_UART_Transmit(&huart1, _msg,_len, 10);
// HAL_UART_Transmit_IT(&huart1,_msg,_len);
// HAL_Delay(time);
// free(_msg);
// free(uart1.buffer);
}
void write_data_slave_F3(uint8_t id,uint8_t fuction,uint16_t value_add,uint16_t value_cnt,uint8_t _len,uint16_t time)
{
_msg[0]=id&0xFF;//id
_msg[1]=fuction&0xFF;//idfuction
_msg[2]= value_add>>8;
_msg[3]= value_add&0xFF;
_msg[4]= value_cnt>>8;
_msg[5]= value_cnt&0xFF;
crc(_msg,_len-2);
_msg[6]=CRCLo ;
_msg[7]=CRCHi ;
for(i=0;i<_len;i++)
{
putchar1(_msg[i]);
}
// HAL_UART_Transmit_IT(&huart1,_msg,_len);
// HAL_Delay(time);
}
void write_data_slave_F16(uint16_t data,uint16_t value_add,uint16_t value_cnt,uint8_t byte_cnt,uint8_t _len,uint16_t time)
{
_msg[0]=0x01;//id
_msg[1]=0x10;//id
_msg[2]= value_add>>8;
_msg[3]= value_add&0xFF;
_msg[ 4]= value_cnt>>8;
_msg[5]= value_cnt&0xFF;
_msg[6]=byte_cnt&0xFF;//bytte cnt
_msg[7]=data>>8;
_msg[8]=data&0xFF;
crc(_msg,_len-2);
_msg[9]=CRCLo ;
_msg[10]=CRCHi ;
for(i=0;i<_len;i++)
{
putchar1(_msg[i]);
}
// HAL_UART_Transmit_IT(&huart1,_msg,_len);
// HAL_Delay(time);
}
Hàm nhận giữ liệu ngắt UART
uint8_t data_rx;
uint8_t RX_BUF[200];
uint8_t RXi=0;
void USART1_IRQHandler(void)
{
if ((USART1->SR & USART_FLAG_RXNE) != (u16)RESET)
{
TIM_ITConfig(TIM3, TIM_IT_Update,ENABLE);
USART_ClearITPendingBit(USART1,USART_IT_RXNE);
data_rx =USART1->DR&0xFF;
RX_BUF[RXi] = data_rx;
RXi++;
}
}
Hàm ngắt timer để nhận giữ liệu UART
long int count_tim2=0;
void TIM2_IRQHandler(void)
{
count_tim2++;
switch(count_tim2)
{
// case 100: write_data_slave_F3(1,3,0,2,8,10);break;
// case 200: write_data_slave_F16(65535,0,1,2,11,10); break;
case 300:write_data_slave_F1(1,1,0,16,8,10);break;
case 400:break;
case 500:break;
case 600:break;
case 1000:count_tim2=0;break;
}
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
//if(++count_tim7>1000) {printf("TIM2: %u \r\n",1234);count_tim7=0;}
}
long int count_tim3=0;
void TIM3_IRQHandler(void)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
count_tim3++;
//if(++count_tim7>1000) {printf("TIM3: %u \r\n",1234);count_tim7=0;}
}
Hàm main.c
/**
******************************************************************************
* @file main.c
* @author MCD Application Team
* @version V1.0.0
* @date 18-April-2011
* @brief Main program body
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx.h"
#include "usart.h"
#include "config.h"
#include <stdlib.h>
#include "systick.h"
#include "config_int.h"
#include "fuction_code.h"
#ifdef __GNUC__
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
#define USER_KEY_Port GPIOC
#define USER_KEY_Pin GPIO_Pin_7
#define USER_KEY_RCC_AHBPeriph RCC_AHB1Periph_GPIOC
/* CAN BUS KHOI TAO*/
__IO uint8_t Can1Flag,Can2Flag;
/* CAN BUS KHOI TAO*/
/*MODBUS KHOI TAO*/
uint8_t CRCLo;
uint8_t CRCHi;
uint8_t _msg[100];
extern uint8_t data_rx;
extern uint8_t RX_BUF[200];
extern uint8_t RXi;
extern long int count_tim3;
int cnt_mb=0;
/*MODBUS KHOI TAO*/
void CAN1_Config(void);
void CAN2_Config(void);
void NVIC_Config_Can(void);
void Can1WriteData(uint16_t ID);
void Can2WriteData(uint16_t ID);
extern __IO uint32_t TimmingDelay;
void delay_ms1(__IO uint32_t time);
/* Private functions ---------------------------------------------------------*/
/**
* @brief Main program.
* @param None
* @retval None
*/
int main(void)
{
uint8_t error_can=0;
USART_Configuration();
//USART_NVIC_Config();
// printf("\r\nCAN-Bus Test \r\n");
// printf("CAN-Bus Speed 100kHz \r\n");
//printf("Please press the JOYSTICK middle button to continue!\r\n");
SysTick_Config(SystemCoreClock/1000);
CAN1_Config();
CAN2_Config();
NVIC_Config_Can();
Config_int_time7();
Config_int_time2();
Config_int_time3();
//delay_init();
/* Infinite loop */
while (1)
{
if(count_tim3>100)
{
TIM_ITConfig(TIM3, TIM_IT_Update,DISABLE);
count_tim3=0;RXi=0;
/*
for(cnt_mb=0;cnt_mb<20;cnt_mb++)
{
printf("\r\nCAN-Bus Test:%x \r\n",RX_BUF[cnt_mb]);
}
*/
}
// TxMessage.Data[0] = 0x12;
// CAN_Transmit(CAN1, &TxMessage);
// TxMessage.Data[0] = 0x02;
// CAN_Transmit(CAN2, &TxMessage);
// delay_ms1(10);
if( Can2Flag == ENABLE )
{
Can2Flag = DISABLE;
printf("CAN2 Receive Data \r\n");
}
if( Can1Flag == ENABLE )
{
Can1Flag = DISABLE;
printf("CAN1 Receive Data \r\n");
}
}
}
void delay_ms1(__IO uint32_t time)
{
TimmingDelay = time;
while(TimmingDelay !=0);
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
Liên hệ với linhkienhdshop.com để lấy code và thư viện