PC通过485与51单片机通讯去控制继电器,如何编单片机C语言程序?

PC通过485与51单片机通讯去控制继电器,如何编单片机C语言程序?,第1张

51对于继电器的控制,只用高低电平就可以了。关键是,你在明晌你的程序里要有一个判断子程序,判断单片机从PC机(通过RS485)穿过来的谨贺是什么数据,从而对单片机的某位置位或者复位。比如:你可以用一个if语句,如果收到的数据时11111,在置位,如果收到的数据时00000,则复位,相应的继激晌锋电器就会动作了。

/*

* 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 nn<8n++)

{

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=0i<4i++)

{

PORTB|=_BV(PB0)

_delay_ms(1)

Send_Char(ADC_Buffer[i])

_delay_ms(1)

PORTB&=~_BV(PB0)

}

break

}

UCSRB|=_BV(RXCIE)

}


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/8223047.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-14
下一篇 2023-04-14

发表评论

登录后才能评论

评论列表(0条)

保存