當前位置:編程學習大全網 - 編程語言 - 您好,有沒有關於單片機RS485多機通信的c語言程序啊

您好,有沒有關於單片機RS485多機通信的c語言程序啊

/*

* MEGA8_485_EEPROM_817_ADC_WDT.c

*

* Created: 2013-8-8 16:52:15

* Author: Administrator

*/

#define F_CPU 4000000UL

#include <avr/io.h>

#include <util/delay.h>

#include <avr/interrupt.h>

#include <string.h>

#include <avr/wdt.h> //看門狗相關頭文件

#include <avr/eeprom.h>

#define INT8U unsigned char

#define INT16U unsigned int

#define INT32U unsigned long

#define BT_NO 0xDE //電池的識別號碼

INT8U eepromx EEMEM;

//全局變量

INT16U ADC_bt_v;

INT8U UART_Send_flag;

INT8U ADC_Buffer[]={0,0,0,0};

static INT32U ADC_bt_Total=0;

INT16U ADC_bt_S;

INT16U ADC_Ref_Buffer[]={0,0};

float ADC_Ref;

INT16U n;

//串口初始化

void Usart_Init(INT16U BAUD)

{

UCSRB =_BV(RXEN)|_BV(TXEN)|_BV(RXCIE); //接收與發送使能,接收與接收結束中斷使能

UCSRC=_BV(UCSZ1)|_BV(UCSZ0)|_BV(UPM1)|_BV(URSEL); //8位數據位、1位停止位、偶校驗

UBRRL=(F_CPU/BAUD/16-1)%256; //設置波特率

UBRRH=(F_CPU/BAUD/16-1)/256;

}

//單字符發送

void Send_Char(char c)

{

while(!(UCSRA&_BV(UDRE))); //判斷數據寄存器是否為空

UDR=c;

while(!(UCSRA&_BV(TXC))); //判斷發送是否結束

UCSRA|=_BV(TXC); //通過置位進行手動清零

}

//串口接收部分

//#define RX_BUFFER_SIZE 2

//uchar rx_buffer[RX_BUFFER_SIZE];

//uchar rx_counter;

//uchar Uart_RecvFlag;

//系統初始化

void System_Init()

{

ADCSRA=0xE6; //10位ADC轉換置位,啟動轉換,64分頻

DDRB|=_BV(PB0); //485的收發模式控制端口,低電平為接收模式,高電平為發送模式

PORTB&=~_BV(PB0);

DDRC&=~_BV(PC0); //ADC0引腳定義

PORTC&=~_BV(PC0);

TCCR1B=0x03; //T1預設分頻:256

TCNT1=65536-F_CPU/64.0*1.5; //晶振4MHZ,1.5S定時初值

TIMSK=0x04; //允許T1定時器溢出中斷

wdt_enable(WDTO_2S); //啟動看門狗(溢出時間1.9S,約等於2.0S)

/* WDTCSR=0x0F;*/

DDRD&=~_BV(PD2); //INT0中斷引腳定義

PORTD|=_BV(PD2);

MCUCR=0x00; //INT0中斷低電平觸發

GICR=0XC0; //INT0中斷使能

DDRD&=~_BV(PD3); //INT1中斷引腳定義

PORTD|=_BV(PD3);

// EICRA=0x00; //INT1中斷低電平觸發

eeprom_busy_wait();

ADC_Ref_Buffer[0]=(INT16U)eeprom_read_byte(1);

eeprom_busy_wait();

ADC_Ref_Buffer[1]=(INT16U)eeprom_read_byte(2);

ADC_Ref=(float)(ADC_Ref_Buffer[0]*100.0+ADC_Ref_Buffer[1]);

DDRC|=_BV(PC4); //測試引腳

PORTC|=_BV(PC4);

sei(); //開總中斷

}

//------------------------------------------------------------

//對通道CH進行模數轉換

//------------------------------------------------------------

INT16U ADC_Convert(void)

{

INT16U Result;

ADMUX=0xC0; //ADC0通道,使用內部參考電壓1.1V

Result=(INT16U)((ADCL+(ADCH<<8))*ADC_Ref/1024.0*83.0/68.0+ADC_Ref);

return Result;

}

INT16U ADC_T()

{

INT16U ADC_bt;

ADC_bt=ADC_Convert();

ADCSRA=0xE6;

_delay_us(500); //延時後重新再讀取ADC,關鍵點

ADC_bt=ADC_Convert();

ADCSRA=0xE6;

return ADC_bt;

}

int main(void)

{

Usart_Init(9600);

System_Init();

_delay_ms(1000);

while(1)

{

_delay_ms(10);

}

}

//--------------------------

//外部中斷1中斷函數

//--------------------------

ISR(INT1_vect)

{

PORTC&=~_BV(PC4);

TIMSK=0X00;

}

//--------------------------

//INT0中斷函數,用來校正參考電壓

//--------------------------

ISR(INT0_vect)

{

//校正參考電壓,要用標準2.200V電壓來校正

INT16U ADC_C;

ADCSRA=0xE6; //10位ADC轉換置位,啟動轉換,64分頻

ADMUX=0xC0; //ADC0通道,使用內部參考電壓1.1V

ADC_C=(INT16U)(ADCL+(ADCH<<8));

ADC_Ref=4035.0/(ADC_C/1024.0*83.0/68.0+1); //要用標準2.200V來校正,精度要盡量高

ADC_Ref_Buffer[0]=ADC_Ref/100;

ADC_Ref_Buffer[1]=(INT16U)ADC_Ref%100;

eeprom_busy_wait();

eeprom_write_byte(1,ADC_Ref_Buffer[0]);

eeprom_busy_wait();

eeprom_write_byte(2,ADC_Ref_Buffer[1]);

}

//-------------------------------

//定時器1中斷程序負責餵狗(1.9S以內)

//-------------------------------

ISR(TIMER1_OVF_vect)

{

TCNT1=65536-F_CPU/64.0*1.5; //重裝初值

wdt_reset(); //看門狗復位

}

//USART串口通信接收中斷函數

ISR(USART_RXC_vect)

{

INT8U data;

data=UDR;

sei(); //開總中斷,實現中斷嵌套

UCSRB&=~_BV(RXCIE);

switch (data)

{

case BT_NO:

for (INT8U n;n<8;n++)

{

ADC_bt_S=ADC_T();

ADC_bt_Total=(INT32U)(ADC_bt_Total+ADC_bt_S);

}

ADC_bt_v=(INT16U)(ADC_bt_Total/8.0);

ADC_bt_Total=0;

ADC_Buffer[0]=ADC_bt_v/1000;

ADC_Buffer[1]=ADC_bt_v/100%10;

ADC_Buffer[2]=ADC_bt_v/10%10;

ADC_Buffer[3]=ADC_bt_v%10;

PORTB|=_BV(PB0);

_delay_ms(1);

Send_Char(BT_NO); //表明哪個電池分送的信號

_delay_ms(1);

PORTB&=~_BV(PB0);

PORTB|=_BV(PB0);

_delay_ms(1);

Send_Char(ADC_Ref_Buffer[0]); //MCU參考電壓高位

_delay_ms(1);

PORTB&=~_BV(PB0);

PORTB|=_BV(PB0);

_delay_ms(1);

Send_Char(ADC_Ref_Buffer[1]); //MCU參考電壓低位

_delay_ms(1);

PORTB&=~_BV(PB0);

for (INT8U i=0;i<4;i++)

{

PORTB|=_BV(PB0);

_delay_ms(1);

Send_Char(ADC_Buffer[i]);

_delay_ms(1);

PORTB&=~_BV(PB0);

}

break;

}

UCSRB|=_BV(RXCIE);

}

  • 上一篇:求關於親情、校園、成長、磨練、社會、自然的作文素材,只需素材,中考要用,最好比較新奇。
  • 下一篇:拳皇98連續技出招表
  • copyright 2024編程學習大全網