Updated AVR port to work on actual hardware.
This commit is contained in:
@@ -216,11 +216,6 @@ static uint8_t TransmitPacketDest;
|
|||||||
/* of a frame the node is transmitting: 20 bit times. */
|
/* of a frame the node is transmitting: 20 bit times. */
|
||||||
#define Tframe_gap 20
|
#define Tframe_gap 20
|
||||||
|
|
||||||
/* The maximum time after the end of the stop bit of the final */
|
|
||||||
/* octet of a transmitted frame before a node must disable its */
|
|
||||||
/* EIA-485 driver: 15 bit times. */
|
|
||||||
#define Tpostdrive 15
|
|
||||||
|
|
||||||
/* The maximum time a node may wait after reception of a frame that expects */
|
/* The maximum time a node may wait after reception of a frame that expects */
|
||||||
/* a reply before sending the first octet of a reply or Reply Postponed */
|
/* a reply before sending the first octet of a reply or Reply Postponed */
|
||||||
/* frame: 250 milliseconds. */
|
/* frame: 250 milliseconds. */
|
||||||
|
|||||||
@@ -25,16 +25,16 @@
|
|||||||
#ifndef HARDWARE_H
|
#ifndef HARDWARE_H
|
||||||
#define HARDWARE_H
|
#define HARDWARE_H
|
||||||
|
|
||||||
|
/* The processor clock frequency */
|
||||||
|
#define F_CPU (7372800)
|
||||||
|
|
||||||
#include <avr/io.h>
|
#include <avr/io.h>
|
||||||
#include <avr/interrupt.h>
|
#include <avr/interrupt.h>
|
||||||
|
#include <util/delay.h>
|
||||||
#include "avr035.h"
|
#include "avr035.h"
|
||||||
|
|
||||||
#if !defined(__AVR_ATmega168__)
|
#if !defined(__AVR_ATmega168__)
|
||||||
#error Firmware is configured for ATmega168 only.
|
#error Firmware is configured for ATmega168 only.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* The processor clock frequency */
|
|
||||||
#define FREQ_CPU (7372800)
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -36,10 +36,16 @@
|
|||||||
/* For porting to IAR, see:
|
/* For porting to IAR, see:
|
||||||
http://www.avrfreaks.net/wiki/index.php/Documentation:AVR_GCC/IarToAvrgcc*/
|
http://www.avrfreaks.net/wiki/index.php/Documentation:AVR_GCC/IarToAvrgcc*/
|
||||||
|
|
||||||
|
/* Notice: Fuse Bit Settings
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
void init(void)
|
void init(void)
|
||||||
{
|
{
|
||||||
/* Initialize the Clock Prescaler for ATmega48/88/168 */
|
/* Initialize the Clock Prescaler for ATmega48/88/168 */
|
||||||
/* The device is shipped with the CKDIV8 Fuse programmed */
|
|
||||||
/* The default CLKPSx bits are factory set to 0011 */
|
/* The default CLKPSx bits are factory set to 0011 */
|
||||||
/* Enbable the Clock Prescaler */
|
/* Enbable the Clock Prescaler */
|
||||||
CLKPR = _BV(CLKPCE);
|
CLKPR = _BV(CLKPCE);
|
||||||
@@ -59,7 +65,7 @@ void init(void)
|
|||||||
/* Set the CLKPS3..0 bits to Prescaler of 1 */
|
/* Set the CLKPS3..0 bits to Prescaler of 1 */
|
||||||
CLKPR = 0;
|
CLKPR = 0;
|
||||||
/* Initialize I/O ports */
|
/* Initialize I/O ports */
|
||||||
/* For Port DDRx (Data Direction) Input=1, Output=1 */
|
/* For Port DDRx (Data Direction) Input=0, Output=1 */
|
||||||
/* For Port PORTx (Bit Value) TriState=0, High=1 */
|
/* For Port PORTx (Bit Value) TriState=0, High=1 */
|
||||||
DDRB = 0;
|
DDRB = 0;
|
||||||
PORTB = 0;
|
PORTB = 0;
|
||||||
@@ -79,15 +85,62 @@ void init(void)
|
|||||||
/* Configure Timer0 for millisecond timer */
|
/* Configure Timer0 for millisecond timer */
|
||||||
Timer_Initialize();
|
Timer_Initialize();
|
||||||
|
|
||||||
|
/* Set the LED ports OFF */
|
||||||
|
BIT_SET(PORTD,PD4);
|
||||||
|
BIT_SET(PORTD,PD5);
|
||||||
|
/* Configure the LED ports as outputs */
|
||||||
|
BIT_SET(DDRD,DDD4);
|
||||||
|
BIT_SET(DDRD,DDD5);
|
||||||
|
|
||||||
/* Enable global interrupts */
|
/* Enable global interrupts */
|
||||||
sei();
|
sei();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint8_t NPDU_Timer;
|
||||||
|
|
||||||
|
static void NDPU_Timers(void)
|
||||||
|
{
|
||||||
|
if (NPDU_Timer) {
|
||||||
|
NPDU_Timer--;
|
||||||
|
if (NPDU_Timer == 0) {
|
||||||
|
BIT_SET(PORTD,PD5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void NPDU_LED_On(void)
|
||||||
|
{
|
||||||
|
BIT_CLEAR(PORTD,PD5);
|
||||||
|
NPDU_Timer = 20;
|
||||||
|
}
|
||||||
|
|
||||||
void task_milliseconds(void)
|
void task_milliseconds(void)
|
||||||
{
|
{
|
||||||
while (Timer_Milliseconds) {
|
while (Timer_Milliseconds) {
|
||||||
Timer_Milliseconds--;
|
Timer_Milliseconds--;
|
||||||
/* add other millisecond timer tasks here */
|
/* add other millisecond timer tasks here */
|
||||||
|
RS485_LED_Timers();
|
||||||
|
NDPU_Timers();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t Address_Switch;
|
||||||
|
|
||||||
|
void input_switch_read(void)
|
||||||
|
{
|
||||||
|
uint8_t value;
|
||||||
|
static uint8_t old_value = 0;
|
||||||
|
|
||||||
|
value = BITMASK_CHECK(PINC,0x0F) | (BITMASK_CHECK(PINB,0x07)<<4);
|
||||||
|
if (value != old_value) {
|
||||||
|
old_value = value;
|
||||||
|
} else {
|
||||||
|
if (old_value != Address_Switch) {
|
||||||
|
Address_Switch = old_value;
|
||||||
|
#if defined(BACDL_MSTP)
|
||||||
|
dlmstp_set_mac_address(Address_Switch);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,7 +164,6 @@ int main(void)
|
|||||||
init();
|
init();
|
||||||
#if defined(BACDL_MSTP)
|
#if defined(BACDL_MSTP)
|
||||||
RS485_Set_Baud_Rate(38400);
|
RS485_Set_Baud_Rate(38400);
|
||||||
dlmstp_set_mac_address(86);
|
|
||||||
dlmstp_set_max_master(127);
|
dlmstp_set_max_master(127);
|
||||||
dlmstp_set_max_info_frames(1);
|
dlmstp_set_max_info_frames(1);
|
||||||
#endif
|
#endif
|
||||||
@@ -121,6 +173,7 @@ int main(void)
|
|||||||
iam_send(&Handler_Transmit_Buffer[0]);
|
iam_send(&Handler_Transmit_Buffer[0]);
|
||||||
#endif
|
#endif
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
input_switch_read();
|
||||||
task_milliseconds();
|
task_milliseconds();
|
||||||
/* other tasks */
|
/* other tasks */
|
||||||
/* BACnet handling */
|
/* BACnet handling */
|
||||||
@@ -129,6 +182,7 @@ int main(void)
|
|||||||
#if !defined(TEST_MSTP)
|
#if !defined(TEST_MSTP)
|
||||||
npdu_handler(&src, &PDUBuffer[0], pdu_len);
|
npdu_handler(&src, &PDUBuffer[0], pdu_len);
|
||||||
#endif
|
#endif
|
||||||
|
NPDU_LED_On();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,10 @@
|
|||||||
#include "hardware.h"
|
#include "hardware.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
|
||||||
|
/* Timers for turning off the TX,RX LED indications */
|
||||||
|
static uint8_t LED1_Off_Timer;
|
||||||
|
static uint8_t LED3_Off_Timer;
|
||||||
|
|
||||||
/* baud rate */
|
/* baud rate */
|
||||||
static uint32_t RS485_Baud = 38400;
|
static uint32_t RS485_Baud = 38400;
|
||||||
|
|
||||||
@@ -52,6 +56,13 @@ static uint32_t RS485_Baud = 38400;
|
|||||||
#define Tturnaround (40UL)
|
#define Tturnaround (40UL)
|
||||||
/* turnaround_time_milliseconds = (Tturnaround*1000UL)/RS485_Baud; */
|
/* turnaround_time_milliseconds = (Tturnaround*1000UL)/RS485_Baud; */
|
||||||
|
|
||||||
|
/* The maximum time after the end of the stop bit of the final */
|
||||||
|
/* octet of a transmitted frame before a node must disable its */
|
||||||
|
/* EIA-485 driver: 15 bit times. */
|
||||||
|
/* NOTE: AVR lib delay_us limit is 768us; limit is 7bits/9600bps=729us */
|
||||||
|
#define Tpostdrive1 (7UL)
|
||||||
|
#define Tpostdrive2 (7UL)
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* DESCRIPTION: Initializes the RS485 hardware and variables, and starts in
|
* DESCRIPTION: Initializes the RS485 hardware and variables, and starts in
|
||||||
* receive mode.
|
* receive mode.
|
||||||
@@ -75,8 +86,14 @@ void RS485_Initialize(void)
|
|||||||
/* Clear Power Reduction USART0 */
|
/* Clear Power Reduction USART0 */
|
||||||
BIT_CLEAR(PRR,PRUSART0);
|
BIT_CLEAR(PRR,PRUSART0);
|
||||||
/* Use port PD2 for RTS - enable and disable of Transceiver Tx/Rx */
|
/* Use port PD2 for RTS - enable and disable of Transceiver Tx/Rx */
|
||||||
/* Set port bit as Output */
|
/* Set port bit as Output - initially receiving */
|
||||||
|
BIT_CLEAR(PORTD,PD2);
|
||||||
BIT_SET(DDRD,DDD2);
|
BIT_SET(DDRD,DDD2);
|
||||||
|
/* Configure Transmit and Receive LEDs - initially off */
|
||||||
|
BIT_SET(PORTD,PD6);
|
||||||
|
BIT_SET(PORTD,PD7);
|
||||||
|
BIT_SET(DDRD,DDD6);
|
||||||
|
BIT_SET(DDRD,DDD7);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -113,7 +130,7 @@ bool RS485_Set_Baud_Rate(uint32_t baud)
|
|||||||
/* 2x speed mode */
|
/* 2x speed mode */
|
||||||
BIT_SET(UCSR0A,U2X0);
|
BIT_SET(UCSR0A,U2X0);
|
||||||
/* configure baud rate */
|
/* configure baud rate */
|
||||||
UBRR0 = (FREQ_CPU / (8UL * RS485_Baud)) - 1;
|
UBRR0 = (F_CPU / (8UL * RS485_Baud)) - 1;
|
||||||
/* FIXME: store the baud rate */
|
/* FIXME: store the baud rate */
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -153,11 +170,63 @@ void RS485_Transmitter_Enable(bool enable)
|
|||||||
{
|
{
|
||||||
if (enable) {
|
if (enable) {
|
||||||
BIT_SET(PORTD,PD2);
|
BIT_SET(PORTD,PD2);
|
||||||
} else {
|
} else {
|
||||||
|
#if Tpostdrive1
|
||||||
|
_delay_us(Tpostdrive1/RS485_Baud);
|
||||||
|
#endif
|
||||||
|
#if Tpostdrive2
|
||||||
|
_delay_us(Tpostdrive2/RS485_Baud);
|
||||||
|
#endif
|
||||||
BIT_CLEAR(PORTD,PD2);
|
BIT_CLEAR(PORTD,PD2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* DESCRIPTION: Timers for delaying the LED indicators going off
|
||||||
|
* RETURN: none
|
||||||
|
* ALGORITHM: none
|
||||||
|
* NOTES: expected to be called once a millisecond
|
||||||
|
*****************************************************************************/
|
||||||
|
void RS485_LED_Timers(void)
|
||||||
|
{
|
||||||
|
if (LED1_Off_Timer) {
|
||||||
|
LED1_Off_Timer--;
|
||||||
|
if (LED1_Off_Timer == 0) {
|
||||||
|
BIT_SET(PORTD,PD6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (LED3_Off_Timer) {
|
||||||
|
LED3_Off_Timer--;
|
||||||
|
if (LED3_Off_Timer == 0) {
|
||||||
|
BIT_SET(PORTD,PD7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* DESCRIPTION: Turn on the LED, and set the off timer to turn it off
|
||||||
|
* RETURN: none
|
||||||
|
* ALGORITHM: none
|
||||||
|
* NOTES: none
|
||||||
|
*****************************************************************************/
|
||||||
|
static void RS485_LED1_On(void)
|
||||||
|
{
|
||||||
|
BIT_CLEAR(PORTD,PD6);
|
||||||
|
LED1_Off_Timer = 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* DESCRIPTION: Turn on the LED, and set the off timer to turn it off
|
||||||
|
* RETURN: none
|
||||||
|
* ALGORITHM: none
|
||||||
|
* NOTES: none
|
||||||
|
*****************************************************************************/
|
||||||
|
static void RS485_LED3_On(void)
|
||||||
|
{
|
||||||
|
BIT_CLEAR(PORTD,PD7);
|
||||||
|
LED3_Off_Timer = 20;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* DESCRIPTION: Send some data and wait until it is sent
|
* DESCRIPTION: Send some data and wait until it is sent
|
||||||
* RETURN: none
|
* RETURN: none
|
||||||
@@ -168,6 +237,7 @@ void RS485_Send_Data(
|
|||||||
uint8_t * buffer, /* data to send */
|
uint8_t * buffer, /* data to send */
|
||||||
uint16_t nbytes) /* number of bytes of data */
|
uint16_t nbytes) /* number of bytes of data */
|
||||||
{
|
{
|
||||||
|
RS485_LED3_On();
|
||||||
while (nbytes) {
|
while (nbytes) {
|
||||||
while (!BIT_CHECK(UCSR0A,UDRE0)) {
|
while (!BIT_CHECK(UCSR0A,UDRE0)) {
|
||||||
/* do nothing - wait until Tx buffer is empty */
|
/* do nothing - wait until Tx buffer is empty */
|
||||||
@@ -176,10 +246,15 @@ void RS485_Send_Data(
|
|||||||
buffer++;
|
buffer++;
|
||||||
nbytes--;
|
nbytes--;
|
||||||
}
|
}
|
||||||
|
while (!BIT_CHECK(UCSR0A,UDRE0)) {
|
||||||
|
/* do nothing - wait until Tx buffer is empty */
|
||||||
|
}
|
||||||
|
/* is the frame sent? */
|
||||||
while (!BIT_CHECK(UCSR0A,TXC0)) {
|
while (!BIT_CHECK(UCSR0A,TXC0)) {
|
||||||
/* do nothing - wait until the entire frame in the
|
/* do nothing - wait until the entire frame in the
|
||||||
Transmit Shift Register has been shifted out */
|
Transmit Shift Register has been shifted out */
|
||||||
}
|
}
|
||||||
|
BIT_CLEAR(UCSR0A,TXC0);
|
||||||
/* per MSTP spec, sort of */
|
/* per MSTP spec, sort of */
|
||||||
Timer_Silence_Reset();
|
Timer_Silence_Reset();
|
||||||
}
|
}
|
||||||
@@ -204,11 +279,12 @@ bool RS485_ReceiveError(void)
|
|||||||
if (BIT_CHECK(UCSR0A,DOR0)) {
|
if (BIT_CHECK(UCSR0A,DOR0)) {
|
||||||
ReceiveError = true;
|
ReceiveError = true;
|
||||||
}
|
}
|
||||||
/* flush the receive buffer */
|
|
||||||
if (ReceiveError) {
|
if (ReceiveError) {
|
||||||
while (BIT_CHECK(UCSR0A,RXC0)) {
|
RS485_LED1_On();
|
||||||
|
/* flush the receive buffer */
|
||||||
|
do {
|
||||||
dummy_data = UDR0;
|
dummy_data = UDR0;
|
||||||
}
|
} while (BIT_CHECK(UCSR0A,RXC0));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ReceiveError;
|
return ReceiveError;
|
||||||
@@ -222,15 +298,16 @@ bool RS485_ReceiveError(void)
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
bool RS485_DataAvailable(uint8_t *data)
|
bool RS485_DataAvailable(uint8_t *data)
|
||||||
{
|
{
|
||||||
bool uart_data = false;
|
bool DataAvailable = false;
|
||||||
|
|
||||||
/* check for data */
|
/* check for data */
|
||||||
if (BIT_CHECK(UCSR0A,RXC0)) {
|
if (BIT_CHECK(UCSR0A,RXC0)) {
|
||||||
*data = UDR0;
|
*data = UDR0;
|
||||||
uart_data = true;
|
DataAvailable = true;
|
||||||
|
RS485_LED1_On();
|
||||||
}
|
}
|
||||||
|
|
||||||
return uart_data;
|
return DataAvailable;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TEST_RS485
|
#ifdef TEST_RS485
|
||||||
|
|||||||
@@ -57,6 +57,8 @@ extern "C" {
|
|||||||
uint32_t RS485_Get_Baud_Rate(void);
|
uint32_t RS485_Get_Baud_Rate(void);
|
||||||
bool RS485_Set_Baud_Rate(uint32_t baud);
|
bool RS485_Set_Baud_Rate(uint32_t baud);
|
||||||
|
|
||||||
|
void RS485_LED_Timers(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
/* Prescaling: 1, 8, 64, 256, 1024 */
|
/* Prescaling: 1, 8, 64, 256, 1024 */
|
||||||
#define TIMER_PRESCALER 64
|
#define TIMER_PRESCALER 64
|
||||||
/* Count: Timer0 counts up to 0xFF and then signals overflow */
|
/* Count: Timer0 counts up to 0xFF and then signals overflow */
|
||||||
#define TIMER_TICKS (FREQ_CPU/TIMER_PRESCALER/1000)
|
#define TIMER_TICKS (F_CPU/TIMER_PRESCALER/1000)
|
||||||
#if (TIMER_TICKS > 0xFF)
|
#if (TIMER_TICKS > 0xFF)
|
||||||
#error Timer Prescaler value is too small
|
#error Timer Prescaler value is too small
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user