您的位置:首页单片机AVR单片机
内容搜索:
阅读内容
背景:#EDF0F5 #FAFBE6 #FFF2E2 #FDE6E0 #F3FFE1 #DAFAF3 #EAEAEF 默认  

AVRGCC RS-485示范程序

[日期:2008-04-11 ] [来源:网络 作者:佚名] [字体: (投递新闻)
从我的实际工程软件中删减而来,没有进行仔细的调试,自由使用但本人不提供任何担保。

或许对初学者有启发作用。

/* Title: Interrupt driven serial example(RS-485).
* Author: Daidai Hu
* Date: 06/2003
* Purpose: Template for RS-485 slave communication program.
* Needed
* Software: AVR-GCC 3.3 to compile
* Needed
* Hardware: ATMega103 board with serial 0 connected to RS-485 bus. */

#include <stdlib.h>
#include <inttypes.h>
#include <string.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>

#define F_CPU 6000000 /* 6MHz. */
#define MAX_RCV_LEN 128 /* Maximal receive message length. */
#define MAX_SND_LEN 128 /* Maximal send message length. */

#define UART_BAUD_SELECT(bps) (F_CPU/((bps)*16L)-1)

#define TICK 2 /* System tick(ms). */
#define SRL_TOUT 20 /* Idle time between serial frames(ms). */

/* D7-D2: Reserved(0).
* D1-D0: Baud rate select, 0=19200, 1=9600..., 3=2400. */
uint8_t ucBaud_g;

/* Const table for baud rate register. */
prog_char aucBdTbl_c[]=
{
UART_BAUD_SELECT(19200),
UART_BAUD_SELECT(9600),
UART_BAUD_SELECT(4800),
UART_BAUD_SELECT(2400),
};

/* Global flag. */
volatile uint8_t ucFlag_g;
#define RECV_ERR 0x01
#define RECV_FRM 0x02
#define SEND_MSG 0x04

#define RS485_TX_ON sbi(PORTC, 0)
#define RS485_TX_OFF cbi(PORTC, 0)

/* Serial buffer. */
uint8_t aucRcvBuf_g[MAX_RCV_LEN], aucSndBuf_g[MAX_SND_LEN];
/* Receive length, send length and now send position. */
volatile uint8_t ucRcvLen_g, ucSndLen_g, ucSndPos_g;
volatile uint8_t ucSrlTout_g; /* Frame time out counter. */

static void Deal_Recv_Msg(void);

int main(void)
{
volatile uint16_t unDelay;

/* Power on delay. */
for (ucBaud_g=0; ucBaud_g<10; ucBaud_g )
{
for (unDelay=0; unDelay<60000; unDelay )
continue;
}

/* Set timer 1 capture interrupt as system tick. */
TCCR1A=0x00;
TCCR1B=0x09;
OCR1AH=((F_CPU*TICK/1000) & 0xFF00)>>8;
OCR1AL=(F_CPU*TICK/1000) & 0xFF;
sbi(TIMSK, OCIE1A); /* Enable interrupt. */

ucBaud_g=eeprom_rb(0x10);

/* Default baud rate=9600. */
if (ucBaud_g>3)
ucBaud_g=1;
/* Set baud rate. */
UBRR=PRG_RDB(&aucBdTbl_c[ucBaud_g]);
/* Enable RxD/TxD and ints. */
UCR=(1<<RXCIE)|(1<<RXEN)|(1<<TXEN);

sei(); /* Enable interrupts. */

while (1)
{
if (ucFlag_g & RECV_FRM)
{
Deal_Recv_Msg();
cli();
ucRcvLen_g=0;
ucFlag_g &= ~(RECV_FRM | RECV_ERR);
sei();
}
}
}

/* Signal handler for receive complete interrupt. */
SIGNAL(SIG_UART_RECV)
{
uint8_t ucFromUart;

ucFromUart=UDR; /* Read the Rx data first. */

/* Check if last command not dealed over. */
if ((ucFlag_g & RECV_FRM) || ucRcvLen_g>=MAX_RCV_LEN)
ucFlag_g |= RECV_ERR;
else if (!(ucFlag_g & SEND_MSG))
aucRcvBuf_g[ucRcvLen_g ]=ucFromUart;

ucFromUart=USR;
if (ucFromUart & ((0x01<<FE) | (0x01<<DOR)))
ucFlag_g |= RECV_ERR;

ucSrlTout_g=SRL_TOUT/TICK; /* Reset the timeout counter. */
}

/* Signal handler for uart data buffer empty interrupt. */
SIGNAL(SIG_UART_DATA)
{
/* Write byte to data buffer. */
UDR=aucSndBuf_g[ucSndPos_g ];

if (ucSndPos_g>=ucSndLen_g) /* If buffer is empty: */
{
cbi(UCR, UDRIE); /* Disable UDRIE interrupt. */
sbi(UCR, TXCIE);
}
}

SIGNAL(SIG_UART_TRANS)
{
cbi(UCR, TXCIE);
RS485_TX_OFF;
ucFlag_g &= ~SEND_MSG; /* Last message was dealed. */
}

SIGNAL(SIG_OUTPUT_COMPARE1A) /* Timer 1 output compare. */
{
if (ucSrlTout_g && !(--ucSrlTout_g))
ucFlag_g |= RECV_FRM;
}

static void Deal_Recv_Msg(void)
{
/* TODO: deal with receive message here. */
if (ucFlag_g & RECV_ERR)
return;
memcpy(aucSndBuf_g, aucRcvBuf_g, ucRcvLen_g);
ucSndLen_g=ucRcvLen_g;

if (ucSndLen_g>=5)
{
ucSndPos_g=0;

cli();

ucRcvLen_g=0;

ucFlag_g &= ~(RECV_FRM | RECV_ERR);
ucFlag_g |= SEND_MSG;

RS485_TX_ON;

sbi(UCR, UDRIE);

sei();
}
}
阅读:
录入:JETTA

推荐 】 【 打印
本文评论
      全部评论
发表评论


点评: 字数
姓名:
赞助商广告