hrefspace

 找回密码
 立即注册
搜索
热搜: PHP PS 程序设计
查看: 418|回复: 0

UART多机通讯模式

[复制链接]

465

主题

472

帖子

1436

积分

大司空

Rank: 5Rank: 5

积分
1436
发表于 2024-4-15 14:08:39 | 显示全部楼层 |阅读模式
主机MEGA16L,代码如下
  1. #include <iom16v.h> #include <macros.h> #define uchar unsigned char unsigned char data; unsigned char timerl; unsigned char timerh; unsigned char time,rr; unsigned char sendbuf[10]; unsigned char recbuf[10]; uchar   addr,fun,message; uchar   realaddr,realfun,keepaddr,al[url=http://www.mcuzx.net]ARM[/url],realalarm;  //  for  ²¦Â뿪¹Ø void delay(unsigned char i) {     for(timerl=0;timerl<i;); } void port_init(void) {  PORTA = 0x3F;  DDRA = 0x00;  PORTB |= 0x08;  //  485  DDRB |= 0x08;  PORTC = 0x00; //m103 output only  DDRC  = 0xFF;  PORTD = 0xC0;  DDRD  = 0x30; } //TIMER0 initialize - prescale:64 // WGM: Normal // desired value: 1mSec // actual value:  1.000mSec (0.0%) void timer0_init(void) {  TCCR0 = 0x00; //stop  TCNT0 = 0x83; //set count   TCCR0 = 0x03; //start timer } #pragma interrupt_handler timer0_ovf_isr:10 void timer0_ovf_isr(void) {  TCNT0 = 0x83; //reload counter value  timerl++;  timerh++; } //TIMER1 initialize - prescale:1024 // WGM: 0) Normal, TOP=0xFFFF // desired value: 1Sec // actual value:  1.000Sec (0.0%) void timer1_init(void) {  TCCR1B = 0x00; //stop  TCNT1H = 0xE1; //setup  TCNT1L = 0x7C;  TCCR1A = 0x00;  TCCR1B = 0x05; //start Timer } #pragma interrupt_handler timer1_ovf_isr:9 void timer1_ovf_isr(void) {  //TIMER1 has overflowed  TCNT1H = 0xE1; //reload counter high value  TCNT1L = 0x7C; //reload counter low value  time++; } //UART0 initialize // desired baud rate: 19200 // actual: baud rate:19231 (0.2%) // char size: 9 bit // parity: Disabled void uart0_init(void) {  UCSRB = 0x00; //disable while setting baud rate  UCSRA = 0x00;  UCSRC = BIT(URSEL) | 0x06;  UBRRL = 0x19; //set baud rate lo  UBRRH = 0x00; //set baud rate hi  UCSRB = 0xDC; } #pragma interrupt_handler uart0_rx_isr:12 void uart0_rx_isr(void) {  //uart has received a character in UDR } #pragma interrupt_handler uart0_tx_isr:14 void uart0_tx_isr(void) {  unsigned char i;   rr ++;  if(rr < 4){     // for(i=0;i<100;i++);  UCSRB &= ~(1<<TXB8);//      UDR = sendbuf[rr];    }   } //call this routine to initialize all peripherals void init_devices(void) {  //stop errant interrupts until set up  CLI(); //disable all interrupts  port_init();  timer0_init();  timer1_init();  uart0_init();  MCUCR = 0x00;  GICR  = 0x00;  TIMSK = 0x05; //timer interrupt sources  SEI(); //re-enable interrupts  //all peripherals are now initialized } void  ReadSwitch(){     unsigned char    i;     realaddr = 0;     realfun = 0;     PORTB &= 0xF8;     DDRB &= 0xF8;     DDRB |= 0x01;     for(i=0; i<40; i++);     if(!(PINA & 0x20))  realaddr |= 0x01;     if(!(PINA & 0x10))  realaddr |= 0x02;     if(!(PINA & 0x08))  realaddr |= 0x04;     if(!(PINA & 0x04))  realaddr |= 0x08;     if(!(PINA & 0x02))  realaddr |= 0x10;     if(!(PINA & 0x01))  realaddr |= 0x20;     DDRB &= 0xF8;     DDRB |= 0x02;     for(i=0; i<40; i++);     if(!(PINA & 0x01))  realaddr |= 0x40;     if(!(PINA & 0x02))  realaddr |= 0x80;     if(!(PINA & 0x04))  realfun |= 0x01;     if(!(PINA & 0x08))  realfun |= 0x02;     if(!(PINA & 0x10))  realfun |= 0x04;     if(!(PINA & 0x20))  realfun |= 0x08;     DDRB &= 0xF8;     DDRB |= 0x04;     for(i=0; i<40; i++);     if(!(PINA & 0x08))  realfun |= 0x40;     if(!(PINA & 0x10))  realfun |= 0x20;     if(!(PINA & 0x20))  realfun |= 0x10;     PORTB |= 0x01;               DDRB &= 0xF8;     DDRB |= 0x01; } unsigned char  checksum() {    return (sendbuf[0]+sendbuf[1]+sendbuf[2]); } void main(void) { unsigned char i;  init_devices();  timerl = 0;  timerh = 0;  time   = 0;   for(;;){        if(timerl > 200){        PORTB ^= 0x01;        timerl = 0;    ReadSwitch();    if(realfun & 0x01){        sendbuf[0]=realaddr;                        sendbuf[1]=0x77;                sendbuf[2]='1';                sendbuf[3]= checksum();        rr = 0;            UCSRB |= (1<<TXB8);               UDR = realaddr;            }    if(realfun & 0x02){        sendbuf[0]=realaddr;        sendbuf[1]=0x77;                sendbuf[2]='2';                sendbuf[3]= checksum();        rr = 0;            UCSRB |= (1<<TXB8);           UDR = realaddr;    }    if(realfun & 0x04){        sendbuf[0]=realaddr;        sendbuf[1]=0x77;                sendbuf[2]='3';                sendbuf[3]= checksum();        rr = 0;            UCSRB |= (1<<TXB8);        UDR = realaddr;    }    if(realfun & 0x08){        sendbuf[0]=realaddr;        sendbuf[1]=0x77;                sendbuf[2]='4';                sendbuf[3]= checksum();        rr = 0;            UCSRB |= (1<<TXB8);        UDR = realaddr;    }    if(realfun & 0x10){        sendbuf[0]= realaddr;        sendbuf[1]= 0x77;                sendbuf[2]= 'F';                sendbuf[3]= checksum();        rr = 0;            UCSRB |= (1<<TXB8);        UDR = realaddr;    }        if(realfun & 0x40){        sendbuf[0]=realaddr;        sendbuf[1]=0x77;                             sendbuf[2]=0x88;                                                                                                                                                                                                          sendbuf[3]= checksum();        rr = 0;            UCSRB |= (1<<TXB8);        UDR = realaddr;    }    if(realfun & 0x20){        sendbuf[0]=realaddr;        sendbuf[1]=0x88;                sendbuf[2]='8';                sendbuf[3]= checksum();        rr = 0;            UCSRB |= (1<<TXB8);        UDR = realaddr;    }       }  }  }
复制代码

多机通讯与普通的USART通讯差不多,只不过注意几点:  
1,需在复位时将UCSRA寄存器中的MPCM位置1  
2,上位机发送地址数据时将第九位置1,这样一来,所有的从机都能通过中断接收到此数据啦各个从机判断接收到的数据是否与自己的地址相符,不符的返回,符合的(只能有1台符合)将MPCM位置0,以便正常的接收发给自己的数据.这些数据的第九位必须为0.其他的从机不会对这些数据产生中断.从而实现多机通讯.
上位机发送 UCSRB |= (1<<TXB8);及第九位数据是1的时候,从机能够能够产生中断,如果第九位0,则从机将数据忽略。如果你发的数据帧:
地址+数据1+数据2+...   
你可以在从机接收到地址数据后,与本机的地址比较,如果相同。说明是发给本机的指令,你可以在中断中将本设置普通的数据模式,用以接收后面的数据。

上面的MEGA16程序是完整的程序,能够在ICCAVR上运行通过的。

下位机是MEGA8
  1. void uart0_init_mulmodel(void) { UCSRB = 0x00; //disable while setting baud rate UCSRA = 0x01; //mul. processor UCSRC = BIT(URSEL) | 0x06; UBRRL = 0x19; //set baud rate lo UBRRH = 0x00; //set baud rate hi UCSRB = 0x94; //9 bit data } void uart0_init_normodel(void) { UCSRB = 0x00; //disable while setting baud rate UCSRA = 0x00; //normal model UCSRC = BIT(URSEL) | 0x06; UBRRL = 0x19; //set baud rate lo UBRRH = 0x00; //set baud rate hi UCSRB = 0x94; //9 bit data } #pragma interrupt_handler uart0_rx_isr:12 void uart0_rx_isr(void) { //uart has received a character in UDR rrr[rr] = UDR; rr++; receivetask(); } //数据接收处理函数 void R_KeLi(void) { kelitimer = 0; switch(rr){ case 1: if(rrr[0] == addr){//判断地址是否与本机地址相等 uart0_init_normodel();//如果相等,将本设置位普通模式来接收后面的数据,如果没有这句,后面的数据(第九位为0)将被忽略 } else{ rr = 0; } break; } }
复制代码
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|hrefspace

GMT+8, 2024-5-9 03:07 , Processed in 0.067974 second(s), 21 queries .

Powered by hrefspace X3.4 Licensed

Copyright © 2022, hrefspace.

快速回复 返回顶部 返回列表