网站公告列表

  没有公告

加入收藏
设为首页
联系站长
您现在的位置: 61IC中国电子在线 >> 技术文库 >> 嵌入式 >> 文章正文
  一个AVRGCC RS-485的模板程序           ★★★ 【字体:
一个AVRGCC RS-485的模板程序
作者:61IC录入    文章来源:本站原创    点击数:    更新时间:2006-4-7    

从我的实际工程软件中删减而来,没有进行仔细的调试,自由使用但本人不提供任何担保。

或许对初学者有启发作用:)

/* 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();
    }
}

               欢迎点击进入:TI德州中文网   (国内唯一针对TI应用的中文技术网站)    文章录入:admin    责任编辑:admin 
  • 上一篇文章:

  • 下一篇文章:
  • 发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
    最新热点 最新推荐 相关文章
    没有相关文章
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)
    站长:61IC 湘ICP备05002478号