⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pc_control_v1.c

📁 通过本实验学习PC机串口与AVR单片机串口之间相互通讯的基本硬件接口电路和软件编程方法
💻 C
字号:
/************************************************************
AVR单片机串口控制应用程序

主要功能:应用PC机串口控制交流电源插座或者照明灯等电器的开关
日期:2004-10-20
作者:肖 鹏   email:www.527dz.com
主页:www.527dz.com

版本:V1.2  2004-10-30
增加了键盘控制电路,同时单片机回送的状态改为直接读取I/O电平确定
************************************************************/
#include <iom8v.h>
#include <macros.h>
#include "Io_define.h"

unsigned char RX_data[4]={0};       //串口接收的数据
unsigned char keyb_state=0;
unsigned char keyc_state=0;
unsigned char RX_counter=0;         //串口接收到的字节数计数器

void UART_init        (void);
void putchar          (unsigned char c); 
void puts             (unsigned char *s);
void UART_rx          (void);
void delay_nms        (unsigned int n);
void Key_control      (unsigned char comm);
void Read_Pin         (void);

void putchar(unsigned char c)        //字符输出函数
  {
     while (!(UCSRA&(1 << UDRE)));   //判断上次发送有没有完成
     UDR = c;    
  }

#pragma interrupt_handler UART_rx: iv_USART_RX
void UART_rx(void)                   //串口接收中断函数
  {
     RX_data[RX_counter] = UDR;
     
     if (RX_data[RX_counter]=='s')
       {
       	  RX_data[0]=RX_data[RX_counter];
       	  RX_counter=0;
       }
     
     RX_counter++;                   //接收的字节数计数
  }

void puts(unsigned char *s)          //字符串发送函数
  {
     while (*s)
       {
       	  putchar(*s);
       	  s++;
       }
  }
  
void UART_init(void)
  {
     UCSRB = BIT(RXCIE)| BIT(RXEN) |BIT(TXEN);   //允许串口发送和接收,并响应接收完成中断
     UBRR = 51;                                  //时钟8Mhz,波特率9600
     UCSRC = BIT(URSEL)|BIT(UCSZ1)|BIT(UCSZ0);   //8位数据+1位stop位
  }
  
void main(void)
  {
     //unsigned char keyb_state=0;
     //unsigned char keyc_state=0;
     unsigned char i=0;
     
     OSCCAL=0xa3;
     
     DDRB  = 0B11000111;       //初始化继电器控制端口      
     PORTB = 0B00000000;
     DDRC  = 0B00111111;
     PORTC = 0B00000000;
     DDRD  = 0B10000000;
     PORTD = 0B00000000;
     
     DDRB |= 0b00111000;           //初始化键盘接口,行为低电平   
     PORTB&= 0b11000111;
     
     DDRD &= ~0b01111000;            //列为高电平
     PORTD|= 0b01111000;
    
     DDRD  &= ~BIT(2);         //设置INT0为输入,高电平状态
     PORTD |= BIT(2);
     GICR  |= BIT(INT0);        //允许INT0外部低电平中断
     
     UART_init();
     
     SEI();
     
     while (1)
       {
         if (RX_counter==4)
           {     
             RX_counter=0;
             if (RX_data[3] == 't')     //接收到PC机发的状态请求指令,则发送
               {                        //控制板的key状态数据给PC
               	 putchar(0);            //控制板地址码
               	 delay_nms(10);
                 putchar(keyb_state);
                 delay_nms(10);
                 putchar(keyc_state);
                 delay_nms(10);
                 putchar('t');          //状态数据标志位
                 delay_nms(10);
               }
             else
             if ((RX_data[0] == 's')&&(RX_data[3] == 'p'))   //检验指令格式是否正确
               {  
                 if ((RX_data[1] == 'u') &&(RX_data[2]=='0'))//是否是软件升级指令
                   {
                     //puts("upready");
                     asm("jmp 0xe00");
                   }
                 else  
                 if (RX_data[1]=='0')                        //地址码是否正确
                   {
                      Key_control(RX_data[2]);                
                   }
               }
          }
     } 
  }
  
void Key_control(unsigned char comm)
  {
     CLI();
     switch (comm)
       {
         case '0':  key0  ^= key0_open;  break;
         case '1':  key1  ^= key1_open;  break;
         case '2':  key2  ^= key2_open;  break;
	 case '3':  key3  ^= key3_open;  break;
         case '4':  key4  ^= key4_open;  break;
         case '5':  key5  ^= key5_open;  break;
         case '6':  key6  ^= key6_open;  break;
         case '7':  key7  ^= key7_open;  break;
         case '8':  key8  ^= key8_open;  break;
         case '9':  key9  ^= key9_open;  break;
         case ':':  key10 ^= key10_open; break;
         case ';':  key11 ^= key11_open; break;  
         case 'a': {
              	     PORTB |= 0B11000111;
              	     PORTC |= 0B00111111;
              	     PORTD |= 0B10000000;
              	   }  break;  
         case 'b': {    
              	     PORTB &= 0B00111000;
              	     PORTC &= 0B11000000;
              	     PORTD &= 0B01111111;
              	   }  break;       	   
                              
      }      
      Read_Pin();
      putchar(0);           //发送控制板地址码和key状态数据
      delay_nms(10);
      putchar(keyb_state);
      delay_nms(10);
      putchar(keyc_state);
      delay_nms(10);
      putchar('t');
      delay_nms(10);
      SEI(); 
  }

void Read_Pin(void)
  {
    asm("nop");
    keyb_state = ((PINB & 0B11000111)|((PINC & 0B00110000)>>1)|
                  ((PIND & 0B10000000)>>2));
    keyc_state = (PINC & 0B00001111);
  }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -