找回密码
 注册会员
更新自动建库工具PCB Footprint Expert 2024.04 Pro / Library Expert 破解版

UART多机通讯模式

[复制链接]
慧龙 发表于 2010-5-25 23:56:55 | 显示全部楼层 |阅读模式

本文包含原理图、PCB、源代码、封装库、中英文PDF等资源

您需要 登录 才可以下载或查看,没有账号?注册会员

×
主机MEGA16L,代码如下

  1. #include <iom16v.h>
  2. #include <macros.h>
  3. #define uchar unsigned char

  4. unsigned char data;
  5. unsigned char timerl;
  6. unsigned char timerh;
  7. unsigned char time,rr;
  8. unsigned char sendbuf[10];
  9. unsigned char recbuf[10];
  10. uchar   addr,fun,message;
  11. uchar   realaddr,realfun,keepaddr,alARM,realalarm;  //  for  &sup2;&brvbar;&Acirc;&euml;&iquest;&ordf;&sup1;&Oslash;

  12. void delay(unsigned char i)
  13. {
  14.     for(timerl=0;timerl<i;);
  15. }
  16. void port_init(void)
  17. {
  18. PORTA = 0x3F;
  19. DDRA = 0x00;
  20. PORTB |= 0x08;  //  485
  21. DDRB |= 0x08;
  22. PORTC = 0x00; //m103 output only
  23. DDRC  = 0xFF;
  24. PORTD = 0xC0;
  25. DDRD  = 0x30;
  26. }

  27. //TIMER0 initialize - prescale:64
  28. // WGM: Normal
  29. // desired value: 1mSec
  30. // actual value:  1.000mSec (0.0%)
  31. void timer0_init(void)
  32. {
  33. TCCR0 = 0x00; //stop
  34. TCNT0 = 0x83; //set count  
  35. TCCR0 = 0x03; //start timer
  36. }

  37. #pragma interrupt_handler timer0_ovf_isr:10
  38. void timer0_ovf_isr(void)
  39. {
  40. TCNT0 = 0x83; //reload counter value
  41. timerl++;
  42. timerh++;
  43. }

  44. //TIMER1 initialize - prescale:1024
  45. // WGM: 0) Normal, TOP=0xFFFF
  46. // desired value: 1Sec
  47. // actual value:  1.000Sec (0.0%)
  48. void timer1_init(void)
  49. {
  50. TCCR1B = 0x00; //stop
  51. TCNT1H = 0xE1; //setup
  52. TCNT1L = 0x7C;
  53. TCCR1A = 0x00;
  54. TCCR1B = 0x05; //start Timer
  55. }

  56. #pragma interrupt_handler timer1_ovf_isr:9
  57. void timer1_ovf_isr(void)
  58. {
  59. //TIMER1 has overflowed
  60. TCNT1H = 0xE1; //reload counter high value
  61. TCNT1L = 0x7C; //reload counter low value
  62. time++;
  63. }

  64. //UART0 initialize
  65. // desired baud rate: 19200
  66. // actual: baud rate:19231 (0.2%)
  67. // char size: 9 bit
  68. // parity: Disabled
  69. void uart0_init(void)
  70. {
  71. UCSRB = 0x00; //disable while setting baud rate
  72. UCSRA = 0x00;
  73. UCSRC = BIT(URSEL) | 0x06;
  74. UBRRL = 0x19; //set baud rate lo
  75. UBRRH = 0x00; //set baud rate hi
  76. UCSRB = 0xDC;
  77. }

  78. #pragma interrupt_handler uart0_rx_isr:12
  79. void uart0_rx_isr(void)
  80. {
  81. //uart has received a character in UDR
  82. }

  83. #pragma interrupt_handler uart0_tx_isr:14
  84. void uart0_tx_isr(void)
  85. {
  86. unsigned char i;  
  87. rr ++;
  88. if(rr < 4){
  89.     // for(i=0;i<100;i++);
  90. UCSRB &= ~(1<<TXB8);//
  91.      UDR = sendbuf[rr];   
  92. }
  93.   
  94. }

  95. //call this routine to initialize all peripherals
  96. void init_devices(void)
  97. {
  98. //stop errant interrupts until set up
  99. CLI(); //disable all interrupts
  100. port_init();
  101. timer0_init();
  102. timer1_init();
  103. uart0_init();

  104. MCUCR = 0x00;
  105. GICR  = 0x00;
  106. TIMSK = 0x05; //timer interrupt sources
  107. SEI(); //re-enable interrupts
  108. //all peripherals are now initialized
  109. }

  110. void  ReadSwitch(){
  111.     unsigned char    i;
  112.     realaddr = 0;
  113.     realfun = 0;
  114.     PORTB &= 0xF8;
  115.     DDRB &= 0xF8;
  116.     DDRB |= 0x01;
  117.     for(i=0; i<40; i++);
  118.     if(!(PINA & 0x20))  realaddr |= 0x01;
  119.     if(!(PINA & 0x10))  realaddr |= 0x02;
  120.     if(!(PINA & 0x08))  realaddr |= 0x04;
  121.     if(!(PINA & 0x04))  realaddr |= 0x08;
  122.     if(!(PINA & 0x02))  realaddr |= 0x10;
  123.     if(!(PINA & 0x01))  realaddr |= 0x20;

  124.     DDRB &= 0xF8;
  125.     DDRB |= 0x02;
  126.     for(i=0; i<40; i++);
  127.     if(!(PINA & 0x01))  realaddr |= 0x40;
  128.     if(!(PINA & 0x02))  realaddr |= 0x80;
  129.     if(!(PINA & 0x04))  realfun |= 0x01;
  130.     if(!(PINA & 0x08))  realfun |= 0x02;
  131.     if(!(PINA & 0x10))  realfun |= 0x04;
  132.     if(!(PINA & 0x20))  realfun |= 0x08;

  133.     DDRB &= 0xF8;
  134.     DDRB |= 0x04;
  135.     for(i=0; i<40; i++);
  136.     if(!(PINA & 0x08))  realfun |= 0x40;
  137.     if(!(PINA & 0x10))  realfun |= 0x20;
  138.     if(!(PINA & 0x20))  realfun |= 0x10;

  139.     PORTB |= 0x01;           
  140.     DDRB &= 0xF8;
  141.     DDRB |= 0x01;
  142. }


  143. unsigned char  checksum()
  144. {
  145.    return (sendbuf[0]+sendbuf[1]+sendbuf[2]);
  146. }

  147. void main(void)
  148. {
  149. unsigned char i;
  150. init_devices();
  151. timerl = 0;
  152. timerh = 0;
  153. time   = 0;  
  154. for(;;){
  155.        if(timerl > 200){
  156.        PORTB ^= 0x01;
  157.        timerl = 0;
  158.    ReadSwitch();
  159.    if(realfun & 0x01){
  160.        sendbuf[0]=realaddr;         
  161.                sendbuf[1]=0x77;
  162.                sendbuf[2]='1';
  163.                sendbuf[3]= checksum();
  164.        rr = 0;
  165.            UCSRB |= (1<<TXB8);        
  166.        UDR = realaddr;
  167.         
  168.    }
  169.    if(realfun & 0x02){
  170.        sendbuf[0]=realaddr;
  171.        sendbuf[1]=0x77;
  172.                sendbuf[2]='2';
  173.                sendbuf[3]= checksum();
  174.        rr = 0;
  175.            UCSRB |= (1<<TXB8);   
  176.        UDR = realaddr;
  177.    }
  178.    if(realfun & 0x04){
  179.        sendbuf[0]=realaddr;
  180.        sendbuf[1]=0x77;
  181.                sendbuf[2]='3';
  182.                sendbuf[3]= checksum();
  183.        rr = 0;
  184.            UCSRB |= (1<<TXB8);
  185.        UDR = realaddr;
  186.    }
  187.    if(realfun & 0x08){
  188.        sendbuf[0]=realaddr;
  189.        sendbuf[1]=0x77;
  190.                sendbuf[2]='4';
  191.                sendbuf[3]= checksum();
  192.        rr = 0;
  193.            UCSRB |= (1<<TXB8);
  194.        UDR = realaddr;
  195.    }
  196.    if(realfun & 0x10){
  197.        sendbuf[0]= realaddr;
  198.        sendbuf[1]= 0x77;
  199.                sendbuf[2]= 'F';
  200.                sendbuf[3]= checksum();
  201.        rr = 0;
  202.            UCSRB |= (1<<TXB8);
  203.        UDR = realaddr;
  204.    }     
  205.    if(realfun & 0x40){
  206.        sendbuf[0]=realaddr;
  207.        sendbuf[1]=0x77;
  208.                             sendbuf[2]=0x88;                                                                                                                                                                                                          sendbuf[3]= checksum();
  209.        rr = 0;
  210.            UCSRB |= (1<<TXB8);
  211.        UDR = realaddr;
  212.    }
  213.    if(realfun & 0x20){
  214.        sendbuf[0]=realaddr;
  215.        sendbuf[1]=0x88;
  216.                sendbuf[2]='8';
  217.                sendbuf[3]= checksum();
  218.        rr = 0;
  219.            UCSRB |= (1<<TXB8);
  220.        UDR = realaddr;
  221.    }   
  222.    }
  223. }  
  224. }

复制代码


多机通讯与普通的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)
  2. {
  3. UCSRB = 0x00; //disable while setting baud rate
  4. UCSRA = 0x01; //mul. processor
  5. UCSRC = BIT(URSEL) | 0x06;
  6. UBRRL = 0x19; //set baud rate lo
  7. UBRRH = 0x00; //set baud rate hi
  8. UCSRB = 0x94; //9 bit data
  9. }
  10. void uart0_init_normodel(void)
  11. {
  12. UCSRB = 0x00; //disable while setting baud rate
  13. UCSRA = 0x00; //normal model
  14. UCSRC = BIT(URSEL) | 0x06;
  15. UBRRL = 0x19; //set baud rate lo
  16. UBRRH = 0x00; //set baud rate hi
  17. UCSRB = 0x94; //9 bit data
  18. }

  19. #pragma interrupt_handler uart0_rx_isr:12
  20. void uart0_rx_isr(void)
  21. {
  22. //uart has received a character in UDR
  23. rrr[rr] = UDR;
  24. rr++;
  25. receivetask();
  26. }
  27. //数据接收处理函数
  28. void R_KeLi(void)
  29. {
  30. kelitimer = 0;
  31. switch(rr){
  32. case 1:
  33. if(rrr[0] == addr){//判断地址是否与本机地址相等
  34. uart0_init_normodel();//如果相等,将本设置位普通模式来接收后面的数据,如果没有这句,后面的数据(第九位为0)将被忽略
  35. }
  36. else{
  37. rr = 0;
  38. }
  39. break;
  40. }

  41. }
复制代码
*滑块验证:
您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

QQ|手机版|MCU资讯论坛 ( 京ICP备18035221号-2 )|网站地图

GMT+8, 2024-12-23 13:47 , Processed in 0.053346 second(s), 9 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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