[Промышленное программирование, Разработка робототехники, Программирование микроконтроллеров, Разработка под Arduino, Производство и разработка электроники] Портирование ModBus Slave RTU/ASCII на IAR AVR v3
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Я уже десять лет не писал под AVR… А вдруг разучился?! Для проверки я решил портировать библиотеку ModBus Slave RTU/ASCII без смс и регистрации на платформу IAR AVR, а также, по просьбам читателей, показать демку подключения к панели оператора Weintek.
Для решения этой задачи в кустах обнаружился рояль ноутбук IBM ThinkPad, нужным комплектом программного обеспечения.
Спаян шнурок для программатора AVReal.
В хламе найдена макетная плата с ATMega48. Фотография макетной платы на на первом рисунке.
Поехали!
Для портирования библиотеки «ModBus Slave RTU/ASCII без смс и регистрации» необходимо написать интерфейсы системного таймера и последовательного порта. У автора нездоровая привычка, писать низкоуровневый ввод/вывод для AVR на ассемблере. В нашем случае, я не буду отказывать себе в своих привычках.
Заголовочный файл systimer.h
SPL
#ifndef __SYSTIMER_H
#define __SYSTIMER_H
#ifdef __SYSTIMER_ASM
#define CLKSysTimer (8000000/64)
#else
#include "main.h"
//Инициализация
void InitSysClock(void);
//время от запуска в милисекундах
unsigned long Clock(void);
#endif
#endif
Файл systimer.asm
SPL
#define __SYSTIMER_ASM
#include <iom48.h>
#include "systimer.h"
MODULE __systimer
COMMON INTVEC
ORG TIMER0_COMPA_vect
rjmp tim0_comp
RSEG CODE
tim0_comp:
in r10,SREG
inc r11
add r12,r11
dec r11
adc r13,r11
adc r14,r11
adc r15,r11
out SREG,r10
reti
PUBLIC InitSysClock
InitSysClock:
cli
clr r11
clr r12
clr r13
clr r14
clr r15
push r16
ldi r16,(0<<COM0A1)|(0<<COM0A0)|(0<<COM0B1)|(0<<COM0B0)|(1<<WGM01)|(0<<WGM00)
out TCCR0A,r16
ldi r16,(0<<FOC0A)|(0<<FOC0B)|(0<<WGM02)|(3<<CS00)
out TCCR0B,r16
ldi r16,(CLKSysTimer/1000)
out OCR0A,r16
ldi r16,(0<<OCIE0B)|(1<<OCIE0A)|(0<<TOIE0)
sts TIMSK0,r16
pop r16
reti
PUBLIC Clock
Clock:
cli
movw r16,r12
movw r18,r14
reti
ENDMOD
END
В качестве системного таймера используется TIMER0. В прерывании по совпадению таймера (COMPA), происходящем каждую милисекунду, инкрементируется четырехбайтная переменная находящаяся в регистрах r12-r15. Эти регистры не поддерживают работу с константами, поэтому для инкремента приходится использовать регистр r11. Регистр r10 используется для сохранения регистра состояния процессора. Перечисленные регистры зарезервированы в настройках компилятора.
Значение переменной r12-r15, через атомарную операцию считывается функцией Clock(), необходимой для работы библиотеки ModBus Slave RTU/ASCII.
Частота прерываний таймера определяется константой CLKSysTimer в заголовочном файле. Значение константы — отношение тактовой частоты процессора к пределителю таймера.
Интерфейс последовательного порта.
Заголовочный файл uart.h
SPL
#ifndef __UART_H
#define __UART_H
#ifdef __UART_ASM
#define CLK_Uart (8000000)
#define UartSpeed (19200)
#define FIFORX (32)
#define FIFOTX (64)
#else
#include "main.h"
void UartInit(void);
unsigned short Inkey16Uart(void);
void PutUart(unsigned char a);
#endif
#endif
Файл uart.asm
SPL
#define __UART_ASM
#include <iom48.h>
#include "uart.h"
MODULE __uartrxtx
RSEG NEAR_Z
rxfifo: //Буфер FIFO
DS FIFORX
rxHead://голова, пишем на голову
DS 1
rxTail://хвост, читаем с хвоста
DS 1
txfifo://Буфер FIFO
DS FIFOTX
txHead://голова, пишем на голову
DS 1
txTail://хвост, читаем с хвоста и в UART
DS 1
COMMON INTVEC
ORG USART_RX_vect
rjmp uart_rx
ORG USART_TX_vect
rjmp uart_tx
RSEG CODE
//void UartInit(void);
PUBLIC UartInit
UartInit:
sbi PORTD,0
cli
push r16
//обнуление указателей
clr r16
sts rxHead,r16
sts rxTail,r16
sts txHead,r16
sts txTail,r16
//Скорость передачи
ldi r16,LOW((CLK_Uart/8+UartSpeed/2)/UartSpeed-1)
sts UBRR0L,r16
ldi r16,HIGH((CLK_Uart/8+UartSpeed/2)/UartSpeed-1)
sts UBRR0H,r16
//Enable receiver and transmitter, разрешение прерываний
ldi r16,(1<<RXEN0)|(1<<TXEN0)|(1<<RXCIE0)|(1<<TXCIE0)
sts UCSR0B,r16
//Set frame format: 8data, 1stop bit, Parity No
ldi r16, (0<<UMSEL00)|(0<<UPM00)|(0<<USBS0)|(3<<UCSZ00)
sts UCSR0C,r16
//сброс флагов прерываний UART
lds r16,UCSR0A
ori r16,(1<<TXC0)|(1<<U2X0)
sts UCSR0A,r16
lds r16,UDR0
pop r16
reti
//Обработчик прерывания по приему
uart_rx:
push r16
in r16,SREG
push r16
push XL
push XH
//UART->FIFO
lds r16,rxHead
ldi XL,LOW(rxfifo)
ldi XH,HIGH(rxfifo)
add XL,r16
adc XH,r16
sub XH,r16
inc r16
andi r16,(FIFORX-1)
sts rxHead,r16
lds r16,UDR0
st X,r16
pop XH
pop XL
pop r16
out SREG,r16
pop r16
reti
//unsigned short Inkey16Uart(void);
//Если нет данных возвращает 0х0000, иначе возвращает 0х01ХХ
PUBLIC Inkey16Uart
Inkey16Uart:
lds R17,rxHead
lds r16,rxTail
cp r16,r17
breq Inkey16Uart1
//читаем данные из FIFO
push XL
push XH
ldi XL,LOW(rxfifo)
ldi XH,HIGH(rxfifo)
add XL,r16
adc XH,r16
sub XH,r16
inc r16
andi r16,(FIFORX-1)
sts rxTail,r16
ld r16,X
pop XH
pop XL
ldi r17,1
ret
Inkey16Uart1:
clr r16
clr r17
ret
//обработчик прерывания по передаче
uart_tx:
push r16
in r16,SREG
push r16
push r17
//проверяем наличие данных в буфере
lds r17,txHead
lds r16,txTail
cp r16,r17
brne uart_tx2
rjmp uart_tx_end
uart_tx2://если данные есть - передаем
push XL
push XH
ldi XL,LOW(txfifo)
ldi XH,HIGH(txfifo)
add XL,r16
adc XH,r16
sub XH,r16
inc r16
andi r16,(FIFOTX-1)
sts txTail,r16
ld r16,X
sts UDR0,r16
pop XH
pop XL
uart_tx_end:
pop r17
pop r16
out SREG,r16
pop r16
reti
//void PutUart(char a);
PUBLIC PutUart
PutUart:
push XL
push XH
//проверяем наличие данных в буфере
lds XH,txHead
lds XL,txTail
cp XH,XL
brne PutUart1
//проверякм регистр передачи
lds XL,UCSR0A
sbrs XL,UDRE0
rjmp PutUart1
sts UDR0,r16
pop XH
pop XL
ret
PutUart1://положить в txfifo[]
push r16
mov r16,XH
ldi XL,LOW(txfifo)
ldi XH,HIGH(txfifo)
add XL,r16
adc XH,r16
sub XH,r16
inc r16
andi r16,(FIFOTX-1)
sts txHead,r16
pop r16
st X,r16
pop XH
pop XL
ret
ENDMOD
END
Интерфейс последовательного порта реализован по классической схеме. Как на прием, так и на передачу реализован тип данных — очередь на кольцевом буфере. Размер буфера приема и передачи определяется константами FIFORX, FIFOTX соответственно. В целях экономии вычислительных ресурсов процессора, размер буферов приема и передачи должен быть кратен 2^N (2,4,8,16,32...), но не больше 256.
Скорость приема/передачи последовательного порта определяется константой UartSpeed. При тактовой частоте микроконтроллера (определяется константой CLK_Uart) 8МГц, то есть, при использовании внутреннего RC-генератора нет возможности использовать высокие скорости передачи.
При попытке скомпилировать файл библиотеки modbus.c, IAR заругался страшными словами. Компилятор IAR AVR не умеет много чего из стандарта С99. Он также не умеет, при использовании модификатора const, размещать объекты в памяти программ, для этого служит специальный модификатор __flash. Пришлось потратить несколько минут для приведения кода в соответствие требованиям компилятора.
В файле библиотеки modbus.h необходимо определить макросы вызова функций последовательного интерфейса и системного таймера.
//Системный таймер, инкрементируется каждую милисекунду
#define ModBusSysTimer Clock()
//Запись байта в поток последовательного порта - void ModBusPUT(unsigned char A)
#define ModBusPUT(A) PutUart(A)
//Чтение байта из потока последовательного порта, - unsigned short ModBusGET(void)
//Если нет данных возвращает 0х0000, иначе возвращает 0х01ХХ
#define ModBusGET() Inkey16Uart()
А также определить количество дискретных входов/выходов, регистров для чтения и регистров для чтения/записи. На этом портирование библиотеки можно считать законченным.
Демка
Для демонстрации возможностей библиотеки ModBus Slave RTU/ASCII подключим наше устройство к панели оператора Weintek. В микроконтроллере организованы часы, значения часов, минут секунд выводятся в регистры Modbus, код содержится в файле ModBus2Prg.c:
void Prg2ModBusOutReg(void)
{//заполнение регистров 4Х регистры для чтения/записи
ModBusOutReg[0]=Seconds;
ModBusOutReg[1]=Minutes;
ModBusOutReg[2]=Hours;
return;
}
void Prg2ModBusInReg(void)
{//заполнение регистов 3Х регистры для чтения
ModBusInReg[0]=Seconds;
ModBusInReg[1]=Minutes;
ModBusInReg[2]=Hours;
return;
}
Через регистры чтения/записи можно произвести установку часов:
void ModBus2PrgOutReg(void)
{//чтение регистров 4Х регистры для чтения/записи
Seconds=ModBusOutReg[0];
Minutes=ModBusOutReg[1];
Hours=ModBusOutReg[2];
return;
}
Дискретные входы/выходы Modbus подключены к портам вывода микроконтроллера. Так же к дискретному входу 4 подключен счетчик полусекунд:
void Prg2ModBusOutBit(void)
{//заполнение регистров дискретных выходов
ModBusOutBit[0].bit0=PORTC_Bit1;
ModBusOutBit[0].bit1=PORTC_Bit2;
ModBusOutBit[0].bit2=PORTC_Bit3;
ModBusOutBit[0].bit3=PORTC_Bit4;
return;
}
void Prg2ModBusInBit(void)
{//заполнение регистров дискретных входов
ModBusInBit[0].bit0=PORTC_Bit1;
ModBusInBit[0].bit1=PORTC_Bit2;
ModBusInBit[0].bit2=PORTC_Bit3;
ModBusInBit[0].bit3=PORTC_Bit4;
ModBusInBit[0].bit4=PoluSeconds;
return;
}
Через дискретные выходы можно управлять состоянием портов микроконтроллера:
void ModBus2PrgOutBit(void)
{//чтение регистров дискретных выходов
PORTC_Bit1=ModBusOutBit[0].bit0;
PORTC_Bit2=ModBusOutBit[0].bit1;
PORTC_Bit3=ModBusOutBit[0].bit2;
PORTC_Bit4=ModBusOutBit[0].bit3;
return;
}
Программное обеспечение панели разрабатывается в среде EasyBuilder Pro v5.
Подключаем микроконтроллер через USB преобразователь к компьютеру, указываем в настройках проекта панели протокол обмена Modbud RTU и настройки COM-порта через который произошло подключение. Запускаем онлайн симуляцию панели.
Код демки с использованием библиотеки ModBus Slave RTU/ASCII со всеми опциями, после компиляции IAR AVR v3 с оптимизацией по скорости оказался на удивление компактным. Он занимает 3024 байта памяти программ, 398 байт памяти данных. Искренне надеюсь, что библиотека ModBus Slave RTU/ASCII найдет широкое применение для разработки Modbus устройств на маломощных микроконтроллерах.
Проект на GitHub
Видео демки
===========
Источник:
habr.com
===========
Похожие новости:
- [Анализ и проектирование систем, Программирование микроконтроллеров, Управление проектами, Производство и разработка электроники, Транспорт] Опыт разработки системы управления для железнодорожной техники на отечественных микроконтроллерах
- [Разработка робототехники, Конференции, Робототехника, Искусственный интеллект, DIY или Сделай сам] Robot Operating System Meetup — 2020/2 пройдет онлайн 5 декабря 2020 года
- [Программирование микроконтроллеров] Полноценный трехпортовый USB-Serial адаптер на STM32 Blue Pill (STM32F103C8T6)
- [Производство и разработка электроники] Гибрид компьютера и IP-телефона. Анатомия аппаратной платформы GM-Box. Часть 3 – тестирование и производство
- [Анализ и проектирование систем, CAD/CAM, Производство и разработка электроники, Электроника для начинающих] Анализ целостности сигналов в PADS Professional (1/6)
- [Производство и разработка электроники, Процессоры] Опубликован конкурс на 32-ядерный процессор «Эльбрус» и стоимость его разработки
- [Разработка под Arduino, DIY или Сделай сам] Самодельный гироскутер
- [Программирование, C#, ООП, Промышленное программирование] Методы без аргументов — зло для неизменяемых объектов, и вот как его полечить
- [Промышленное программирование] Модели и алгоритмы построения цифровой платформы CNCIOT для сбора данных с оборудования
- [Разработка под Arduino, Дизайн, Голосовые интерфейсы] Говорящая открытка, с возможностью записи своего поздравления
Теги для поиска: #_promyshlennoe_programmirovanie (Промышленное программирование), #_razrabotka_robototehniki (Разработка робототехники), #_programmirovanie_mikrokontrollerov (Программирование микроконтроллеров), #_razrabotka_pod_arduino (Разработка под Arduino), #_proizvodstvo_i_razrabotka_elektroniki (Производство и разработка электроники), #_modbus, #_avr, #_weintek, #_promyshlennoe_programmirovanie (
Промышленное программирование
), #_razrabotka_robototehniki (
Разработка робототехники
), #_programmirovanie_mikrokontrollerov (
Программирование микроконтроллеров
), #_razrabotka_pod_arduino (
Разработка под Arduino
), #_proizvodstvo_i_razrabotka_elektroniki (
Производство и разработка электроники
)
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 13:43
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Я уже десять лет не писал под AVR… А вдруг разучился?! Для проверки я решил портировать библиотеку ModBus Slave RTU/ASCII без смс и регистрации на платформу IAR AVR, а также, по просьбам читателей, показать демку подключения к панели оператора Weintek. Для решения этой задачи в кустах обнаружился рояль ноутбук IBM ThinkPad, нужным комплектом программного обеспечения. Спаян шнурок для программатора AVReal. В хламе найдена макетная плата с ATMega48. Фотография макетной платы на на первом рисунке. Поехали! Для портирования библиотеки «ModBus Slave RTU/ASCII без смс и регистрации» необходимо написать интерфейсы системного таймера и последовательного порта. У автора нездоровая привычка, писать низкоуровневый ввод/вывод для AVR на ассемблере. В нашем случае, я не буду отказывать себе в своих привычках. Заголовочный файл systimer.hSPL#ifndef __SYSTIMER_H
#define __SYSTIMER_H #ifdef __SYSTIMER_ASM #define CLKSysTimer (8000000/64) #else #include "main.h" //Инициализация void InitSysClock(void); //время от запуска в милисекундах unsigned long Clock(void); #endif #endif Файл systimer.asmSPL#define __SYSTIMER_ASM
#include <iom48.h> #include "systimer.h" MODULE __systimer COMMON INTVEC ORG TIMER0_COMPA_vect rjmp tim0_comp RSEG CODE tim0_comp: in r10,SREG inc r11 add r12,r11 dec r11 adc r13,r11 adc r14,r11 adc r15,r11 out SREG,r10 reti PUBLIC InitSysClock InitSysClock: cli clr r11 clr r12 clr r13 clr r14 clr r15 push r16 ldi r16,(0<<COM0A1)|(0<<COM0A0)|(0<<COM0B1)|(0<<COM0B0)|(1<<WGM01)|(0<<WGM00) out TCCR0A,r16 ldi r16,(0<<FOC0A)|(0<<FOC0B)|(0<<WGM02)|(3<<CS00) out TCCR0B,r16 ldi r16,(CLKSysTimer/1000) out OCR0A,r16 ldi r16,(0<<OCIE0B)|(1<<OCIE0A)|(0<<TOIE0) sts TIMSK0,r16 pop r16 reti PUBLIC Clock Clock: cli movw r16,r12 movw r18,r14 reti ENDMOD END В качестве системного таймера используется TIMER0. В прерывании по совпадению таймера (COMPA), происходящем каждую милисекунду, инкрементируется четырехбайтная переменная находящаяся в регистрах r12-r15. Эти регистры не поддерживают работу с константами, поэтому для инкремента приходится использовать регистр r11. Регистр r10 используется для сохранения регистра состояния процессора. Перечисленные регистры зарезервированы в настройках компилятора. Значение переменной r12-r15, через атомарную операцию считывается функцией Clock(), необходимой для работы библиотеки ModBus Slave RTU/ASCII. Частота прерываний таймера определяется константой CLKSysTimer в заголовочном файле. Значение константы — отношение тактовой частоты процессора к пределителю таймера. Интерфейс последовательного порта. Заголовочный файл uart.hSPL#ifndef __UART_H
#define __UART_H #ifdef __UART_ASM #define CLK_Uart (8000000) #define UartSpeed (19200) #define FIFORX (32) #define FIFOTX (64) #else #include "main.h" void UartInit(void); unsigned short Inkey16Uart(void); void PutUart(unsigned char a); #endif #endif Файл uart.asmSPL#define __UART_ASM
#include <iom48.h> #include "uart.h" MODULE __uartrxtx RSEG NEAR_Z rxfifo: //Буфер FIFO DS FIFORX rxHead://голова, пишем на голову DS 1 rxTail://хвост, читаем с хвоста DS 1 txfifo://Буфер FIFO DS FIFOTX txHead://голова, пишем на голову DS 1 txTail://хвост, читаем с хвоста и в UART DS 1 COMMON INTVEC ORG USART_RX_vect rjmp uart_rx ORG USART_TX_vect rjmp uart_tx RSEG CODE //void UartInit(void); PUBLIC UartInit UartInit: sbi PORTD,0 cli push r16 //обнуление указателей clr r16 sts rxHead,r16 sts rxTail,r16 sts txHead,r16 sts txTail,r16 //Скорость передачи ldi r16,LOW((CLK_Uart/8+UartSpeed/2)/UartSpeed-1) sts UBRR0L,r16 ldi r16,HIGH((CLK_Uart/8+UartSpeed/2)/UartSpeed-1) sts UBRR0H,r16 //Enable receiver and transmitter, разрешение прерываний ldi r16,(1<<RXEN0)|(1<<TXEN0)|(1<<RXCIE0)|(1<<TXCIE0) sts UCSR0B,r16 //Set frame format: 8data, 1stop bit, Parity No ldi r16, (0<<UMSEL00)|(0<<UPM00)|(0<<USBS0)|(3<<UCSZ00) sts UCSR0C,r16 //сброс флагов прерываний UART lds r16,UCSR0A ori r16,(1<<TXC0)|(1<<U2X0) sts UCSR0A,r16 lds r16,UDR0 pop r16 reti //Обработчик прерывания по приему uart_rx: push r16 in r16,SREG push r16 push XL push XH //UART->FIFO lds r16,rxHead ldi XL,LOW(rxfifo) ldi XH,HIGH(rxfifo) add XL,r16 adc XH,r16 sub XH,r16 inc r16 andi r16,(FIFORX-1) sts rxHead,r16 lds r16,UDR0 st X,r16 pop XH pop XL pop r16 out SREG,r16 pop r16 reti //unsigned short Inkey16Uart(void); //Если нет данных возвращает 0х0000, иначе возвращает 0х01ХХ PUBLIC Inkey16Uart Inkey16Uart: lds R17,rxHead lds r16,rxTail cp r16,r17 breq Inkey16Uart1 //читаем данные из FIFO push XL push XH ldi XL,LOW(rxfifo) ldi XH,HIGH(rxfifo) add XL,r16 adc XH,r16 sub XH,r16 inc r16 andi r16,(FIFORX-1) sts rxTail,r16 ld r16,X pop XH pop XL ldi r17,1 ret Inkey16Uart1: clr r16 clr r17 ret //обработчик прерывания по передаче uart_tx: push r16 in r16,SREG push r16 push r17 //проверяем наличие данных в буфере lds r17,txHead lds r16,txTail cp r16,r17 brne uart_tx2 rjmp uart_tx_end uart_tx2://если данные есть - передаем push XL push XH ldi XL,LOW(txfifo) ldi XH,HIGH(txfifo) add XL,r16 adc XH,r16 sub XH,r16 inc r16 andi r16,(FIFOTX-1) sts txTail,r16 ld r16,X sts UDR0,r16 pop XH pop XL uart_tx_end: pop r17 pop r16 out SREG,r16 pop r16 reti //void PutUart(char a); PUBLIC PutUart PutUart: push XL push XH //проверяем наличие данных в буфере lds XH,txHead lds XL,txTail cp XH,XL brne PutUart1 //проверякм регистр передачи lds XL,UCSR0A sbrs XL,UDRE0 rjmp PutUart1 sts UDR0,r16 pop XH pop XL ret PutUart1://положить в txfifo[] push r16 mov r16,XH ldi XL,LOW(txfifo) ldi XH,HIGH(txfifo) add XL,r16 adc XH,r16 sub XH,r16 inc r16 andi r16,(FIFOTX-1) sts txHead,r16 pop r16 st X,r16 pop XH pop XL ret ENDMOD END Интерфейс последовательного порта реализован по классической схеме. Как на прием, так и на передачу реализован тип данных — очередь на кольцевом буфере. Размер буфера приема и передачи определяется константами FIFORX, FIFOTX соответственно. В целях экономии вычислительных ресурсов процессора, размер буферов приема и передачи должен быть кратен 2^N (2,4,8,16,32...), но не больше 256. Скорость приема/передачи последовательного порта определяется константой UartSpeed. При тактовой частоте микроконтроллера (определяется константой CLK_Uart) 8МГц, то есть, при использовании внутреннего RC-генератора нет возможности использовать высокие скорости передачи. При попытке скомпилировать файл библиотеки modbus.c, IAR заругался страшными словами. Компилятор IAR AVR не умеет много чего из стандарта С99. Он также не умеет, при использовании модификатора const, размещать объекты в памяти программ, для этого служит специальный модификатор __flash. Пришлось потратить несколько минут для приведения кода в соответствие требованиям компилятора. В файле библиотеки modbus.h необходимо определить макросы вызова функций последовательного интерфейса и системного таймера. //Системный таймер, инкрементируется каждую милисекунду
#define ModBusSysTimer Clock() //Запись байта в поток последовательного порта - void ModBusPUT(unsigned char A) #define ModBusPUT(A) PutUart(A) //Чтение байта из потока последовательного порта, - unsigned short ModBusGET(void) //Если нет данных возвращает 0х0000, иначе возвращает 0х01ХХ #define ModBusGET() Inkey16Uart() А также определить количество дискретных входов/выходов, регистров для чтения и регистров для чтения/записи. На этом портирование библиотеки можно считать законченным. Демка Для демонстрации возможностей библиотеки ModBus Slave RTU/ASCII подключим наше устройство к панели оператора Weintek. В микроконтроллере организованы часы, значения часов, минут секунд выводятся в регистры Modbus, код содержится в файле ModBus2Prg.c: void Prg2ModBusOutReg(void)
{//заполнение регистров 4Х регистры для чтения/записи ModBusOutReg[0]=Seconds; ModBusOutReg[1]=Minutes; ModBusOutReg[2]=Hours; return; } void Prg2ModBusInReg(void) {//заполнение регистов 3Х регистры для чтения ModBusInReg[0]=Seconds; ModBusInReg[1]=Minutes; ModBusInReg[2]=Hours; return; } Через регистры чтения/записи можно произвести установку часов: void ModBus2PrgOutReg(void)
{//чтение регистров 4Х регистры для чтения/записи Seconds=ModBusOutReg[0]; Minutes=ModBusOutReg[1]; Hours=ModBusOutReg[2]; return; } Дискретные входы/выходы Modbus подключены к портам вывода микроконтроллера. Так же к дискретному входу 4 подключен счетчик полусекунд: void Prg2ModBusOutBit(void)
{//заполнение регистров дискретных выходов ModBusOutBit[0].bit0=PORTC_Bit1; ModBusOutBit[0].bit1=PORTC_Bit2; ModBusOutBit[0].bit2=PORTC_Bit3; ModBusOutBit[0].bit3=PORTC_Bit4; return; } void Prg2ModBusInBit(void) {//заполнение регистров дискретных входов ModBusInBit[0].bit0=PORTC_Bit1; ModBusInBit[0].bit1=PORTC_Bit2; ModBusInBit[0].bit2=PORTC_Bit3; ModBusInBit[0].bit3=PORTC_Bit4; ModBusInBit[0].bit4=PoluSeconds; return; } Через дискретные выходы можно управлять состоянием портов микроконтроллера: void ModBus2PrgOutBit(void)
{//чтение регистров дискретных выходов PORTC_Bit1=ModBusOutBit[0].bit0; PORTC_Bit2=ModBusOutBit[0].bit1; PORTC_Bit3=ModBusOutBit[0].bit2; PORTC_Bit4=ModBusOutBit[0].bit3; return; } Программное обеспечение панели разрабатывается в среде EasyBuilder Pro v5. Подключаем микроконтроллер через USB преобразователь к компьютеру, указываем в настройках проекта панели протокол обмена Modbud RTU и настройки COM-порта через который произошло подключение. Запускаем онлайн симуляцию панели. Код демки с использованием библиотеки ModBus Slave RTU/ASCII со всеми опциями, после компиляции IAR AVR v3 с оптимизацией по скорости оказался на удивление компактным. Он занимает 3024 байта памяти программ, 398 байт памяти данных. Искренне надеюсь, что библиотека ModBus Slave RTU/ASCII найдет широкое применение для разработки Modbus устройств на маломощных микроконтроллерах. Проект на GitHub Видео демки =========== Источник: habr.com =========== Похожие новости:
Промышленное программирование ), #_razrabotka_robototehniki ( Разработка робототехники ), #_programmirovanie_mikrokontrollerov ( Программирование микроконтроллеров ), #_razrabotka_pod_arduino ( Разработка под Arduino ), #_proizvodstvo_i_razrabotka_elektroniki ( Производство и разработка электроники ) |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 13:43
Часовой пояс: UTC + 5