懒猫爱飞

串口通信调试日志

0
阅读(7446)

这几天刚从51转到AVR还有很多东西不太熟悉,现在用的是mega8515,今天调试串口,都快把我弄崩溃了,开始是能接收不能 发送,到后来是能发送不能接收,再到后为是不能发送比拟能接收……真快把我弄死了,后来再看看寄存器,再看看程序,还是程序的问题,下面是俺开始写的程序:

      //ICC-AVR application builder : 2009-11-24 14:09:56
// Target : M8515
// Crystal: 8.0000Mhz
#include <iom8515v.h>
#include <macros.h>
#define Setbit(REG,N)   REG|=(1<<N)    //对REG的N位置1
#define Clrbit(REG,N)   REG&=~(1<<N)   //对REG的N位清零
#define Invbit(REG,N)   REG^=(1<<N)    //对REG的N位取反
/*_*=============ID指示灯亮/灭宏定义==================*_*/
#define Led_on() Clrbit(PORTD,7)
#define Led_off() Setbit(PORTD,7)
/*>>>>>>>>>>>>>>>>>>>>>>发送使能、发送关闭宏定义<<<<<<<<<<<<<<<<<<<<<*/
#define Send_on() Setbit(PORTD,2)
#define Send_off() Clrbit(PORTD,2)
typedef unsigned char uint8;   /* 定义可移植的无符号8位整数关键字*/
typedef signed   char int8;   /* 定义可移植的有符号8位整数关键字*/
typedef unsigned int uint16;   /* 定义可移植的无符号16位整数关键字*/
typedef signed   int int16;   /* 定义可移植的有符号16位整数关键字*/
typedef unsigned long uint32;   /* 定义可移植的无符号32位整数关键字*/
typedef signed   long int32;   /* 定义可移植的有符号32位整数关键字*/
void port_init(void)
{
PORTA = 0xff;   //初始状态为高电平,为读取设备ID号做准备
DDRA  = 0x00;   //A口做为输入口,用来读取编码开关的值
PORTB = 0x00;   //B口做为输出口,通过2803来控制继电器
DDRB  = 0xFF;
PORTD = 0x80;   //初始状态时灯灭
DDRD  = 0x84;   //PD2控制485芯片的使能端,PD7控制指示灯
}
/**************************************************************/
//UART0 initialize串口初始化
// desired baud rate: 38400
// actual: baud rate:38462 (0.2%)
/*************************************************************/
void uart0_init(void)
{
UCSRB = 0x00;         //disable while setting baud rate
UCSRA = 0x00;
UCSRC =(1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);//0x46;// BIT(URSEL) | 0x06;//异步、无校验、9位数据位
UBRRL = 0x0C;    //UBRRL=(Fosc/16/(Baud+1))%256;  set baud rate lo
UBRRH = 0x00;    //UBRRH=(Fosc/16(Baud+1))/256;   set baud rate hi
UCSRB |=/*(1<<RXCIE)|(1<<RXEN)/*|(1<<TXEN)*/(1<<UCSZ2);//0x94;先关闭发送使能
}
void init_devices(void)
{
//stop errant interrupts until set up
CLI();          //disable all interrupts  (关中断)
port_init();
uart0_init();
MCUCR = 0x00;
EMCUCR = 0x00;
GICR = 0x00;
TIMSK = 0x00;
SEI();         //re-enable interrupts  (开中断)
              //all peripherals are now initialized
}
/*=====================================================*/
void Delay_100us(uint16 t) //100us
{
uint8 i;
while((t--)>0)
{
  for(i=0;i<12;i++);
}
}
void Delay_1ms(void) //1ms
{
uint16 i;
for(i=1;i,(uint16)(8*143-2);i++);
}
void Delay_ms(uint16 tt)//tt ms
{
uint8 i;
while(i<tt)
{
  Delay_1ms();
  i++;
}
}
void Usart_transmit(uint16 data)
{
//UCSRB|=BIT(3);//开启发送使能
while(!(UCSRA&(1<<UDRE)));
//Send_on();
/*******将第九位数复制到TXB8*********/
//while(UCSRB&(~BIT(3)));//等待发送使能
UCSRB&=~(1<<TXB8); //发送的第九位数据一直是0
//if(data&0x0100)
//UCSRB|=(1<<TXB8);
UDR=data;
while(!(UCSRA&(1<<TXC)));
//UCSRC|=(1<<TXC);
//Send_off();
  UCSRB&=~BIT(3);//发送使能关闭
}
void main(void)
{
uint8 i;
init_devices();
//Send_on();
PORTD|=BIT(2);   //485发送使 能
UCSRB|=BIT(3);//发送使能关
while(1)
{
   Led_on();
   //for(i=0;i<10;i++)
   //{
    PORTC="0X58"; //TEST
   Usart_transmit(0x58);  //发送数据
   //Delay_ms(100);
   //Led_off();
   //}
   //UCSRB&=~BIT(3);//发送使能关闭
   //PORTD&=~BIT(2);   //485发送关闭
   //PORTC=0X58; //TEST
   Led_off();
}
}
 
当时我只是查询接收,但接收完了,灯不会灭,也就是程序执行到  Usart_transmit(0x58);  //发送数据  ;就不往下执行了,真弄不明白到底是怎么回事?
……
……
……
经过若干小时的奋斗,现在终于弄出了点眉目,原来是
 PORTC=0X58; //TEST
   Usart_transmit(0x58);  //发送数据
这两句话是不能话在while(1)这个死循环中的,不然程序一直在执行这个死循环,当然就是连续发数据了,应该在这里面写几个条件语句限制才行
   例如:
    if(flag==1)
  {
   PORTB=0xff;
   Usart_transmit(Dat);
   Delay_ms(5000);
   Led_off();
   //flag=0;
  }
  else{Led_on();PORTB=Dat;}
这样的话就不会连续发数据了
不过还是有些其它的问题,只有再看看程序再说了,呵呵,不过终于看到希望了^_^
  下面是俺现在的程序:
   /*===========================================================================*/
// ICC-AVR application builder : 2009-11-6
// Target : M8515
// Crystal: 8.0000Mhz
// Author: Citect Xu
/*==========================================================================*/
#include <iom8515v.h>
#include <macros.h>
#include<stdio.h>
#define Setbit(REG,N)   REG|=(1<<N)    //对REG的N位置1
#define Clrbit(REG,N)   REG&=~(1<<N)   //对REG的N位清零
#define Invbit(REG,N)   REG^=(1<<N)    //对REG的N位取反
/*_*==================ID指示灯亮/灭宏定义=============*_*/
#define Led_on() Clrbit(PORTD,7)
#define Led_off() Setbit(PORTD,7)
/*>>>>>>>>>>>>>>>>>>>>>>发送使能、发送关闭宏定义<<<<<<<<<<<<<<<<<<<<<*/
//Send_on()是485发送使能;Send_off()是485发送关闭
//TX_EN()是单片机串口发送使能;RX_EN()是单片机串口发送关闭
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>^_^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
#define Send_on() Setbit(PORTD,2)
#define Send_off() Clrbit(PORTD,2)
#define TX_EN() UCSRB|=BIT(3)
#define RX_EN() UCSRB&=~BIT(3)
typedef unsigned char uint8;   /* 定义可移植的无符号8位整数关键字*/
typedef signed   char int8;   /* 定义可移植的有符号8位整数关键字*/
typedef unsigned int uint16;   /* 定义可移植的无符号16位整数关键字*/
typedef signed   int int16;   /* 定义可移植的有符号16位整数关键字*/
typedef unsigned long uint32;   /* 定义可移植的无符号32位整数关键字*/
typedef signed   long int32;   /* 定义可移植的有符号32位整数关键字*/
void port_init(void)
{
 PORTA = 0xff;   //初始状态为高电平,为读取设备ID号做准备
 DDRA  = 0x00;   //A口做为输入口,用来读取编码开关的值
 PORTB = 0x00;   //B口做为输出口,通过2803来控制继电器
 DDRB  = 0xFF;
 PORTD = 0x80;   //初始状态时灯灭
 DDRD  = 0x84;   //PD2控制485芯片的使能端,PD7控制指示灯
}
/**************************************************************/
//UART0 initialize串口初始化
// desired baud rate: 38400
// actual: baud rate:38462 (0.2%)
/*************************************************************/
void uart0_init(void)
{
 UCSRB = 0x00;         //disable while setting baud rate
 UCSRA = 0x00;
 UCSRC =(1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);//0x46;// BIT(URSEL) | 0x06;//异步、无校验、9位数据位
 
 UBRRL = 0x0C;    //UBRRL=(Fosc/16/(Baud+1))%256;  set baud rate lo
 UBRRH = 0x00;    //UBRRH=(Fosc/16(Baud+1))/256;   set baud rate hi
 
 UCSRB=(1<<RXCIE)|(1<<RXEN)/*|(1<<TXEN)*/|(1<<UCSZ2);//0x94;先关闭发送使能
}
void init_devices(void)
{
 CLI();          //disable all interrupts  (关中断)
 
 port_init();
 uart0_init();
 MCUCR = 0x00;
 EMCUCR = 0x00;
 GICR = 0x00;
 TIMSK = 0x00;
 
 SEI();         //re-enable interrupts  (开中断)
}
/*=====================================================*/
void Delay_100us(uint16 t) //100us
{
 uint8 i;
 while((t--)>0)
 {
  for(i=0;i<12;i++);
 }
}
void Delay_1ms(void) //1ms
{
 uint16 i;
 for(i=1;i,(uint16)(8*143-2);i++);
}
void Delay_ms(uint16 tt)//tt ms
{
 uint8 i;
 while(i<tt)
 {
  Delay_1ms();
  i++;
 }
}
uint8 Receive_buf[6];
uint8 R_count=0;
uint8 Dat;
uint8 flag="0";
#pragma interrupt_handler uart0_rx_isr:iv_USART0_RXC
/***********************************************************/
//uart has received a character in UDR
//USART接收中断,接收一个字符
/**********************************************************/
void uart0_rx_isr(void) 
{
 CLI();
 if(UCSRB&(1<<RXB8)) 
     {
   Dat="UDR";
   if(Dat==0xff)
   {flag=1;}
   else {flag=0;}
      /*Receive_buf[R_count++]=UDR;
      if(R_count==6)
      {R_count=0;}
      UDR="0X00";*/
      }
 else {
     Dat="0";
       /* uint8 i;
   for(i=0;i<6;i++)
    {
     Receive_buf[i]=0;
    } */
    }
 SEI();

void Usart_transmit(uint8 data)
{
 Send_on();//开启485发送使能
 TX_EN();  //开启串口发送使能
 while(!(UCSRA&(1<<UDRE)));
 //Send_on();
 /*******将第九位数复制到TXB8*********/
 //while(UCSRB&(~BIT(3)));//等待发送使能
 UCSRB&=~(1<<TXB8); //发送的第九位数据一直是0
 //if(data&0x0100)
 //UCSRB|=(1<<TXB8);
 UDR=data;
 while(!(UCSRA&(1<<TXC)));
 //UCSRC|=(1<<TXC);
  Send_off();
  UCSRB&=~BIT(3);//发送使能关闭
}
void main(void)
{
 uint8 i;
 init_devices();
 //Send_on();
 //PORTD|=BIT(2);   //485发送使 能
 //UCSRB|=BIT(3);//发送使能关
  //PORTB=0X01;
 while(1)
 {
  if(flag==1)
  {
   PORTB="0xff";
   Usart_transmit(Dat);
   Delay_ms(5000);
   Led_off();
   //flag=0;
  }
  else{Led_on();PORTB=Dat;}
  /*if(Receive_buf[0]=0xff)
  {
   Led_on();
   PORTB="Receive"_buf[0]; //TEST
   UCSRB|=BIT(3);//发送使能关
   Usart_transmit(Receive_buf[0]);  //发送数据
   Delay_ms(500);
   Led_off();
  }*/
 }
}
 
 
不过现在还是有问题,就是:
      在主程序中
 if(flag==1)
  {
   PORTB="0xff";B口给高电平
   Usart_transmit(Dat); //发送Dat
   Delay_ms(5000);//延时5S
   Led_off();//灯关
   }
           这两句没有好好执行,在实验中发现当我发送0xff时,PORTB口确实是高了一下,而灯也只是闪了一下,为什么没有停在这个状态呢?
          这一情况还没有想明白,还得好好检查一下程序,也得好好理一下思路才行,不然钻进死胡同就完蛋了,不管怎么说吧,俺还是看到了希望的曙光!
         不知道在这里能不能遇到什么大虾什么的前辈否,要是有缘遇到希望能帮俺看一下,谢谢!俺的QQ是515673876;俺的邮箱是:xucun915@126.com