lhy_radio的笔记 https://bbs.21ic.com/?319974 [收藏] [复制] [RSS]

日志

Mega8+LCD1602模拟串口终端---失败

已有 1412 次阅读2009-3-5 01:07 |个人分类:单片机学习|系统分类:单片机

基本思路是将mega8串口接受到的信息先存入存储器(EEPROM)中,同时在LCD上显示两行,
每行15个字符,上下两行的最后一个字符用来显示箭头,指示是否还有未显示信息.
可以通过按键来进行翻页,无数据时相应的箭头就会消失.
还没做完就发现问题了,
存储器选用的是AT24CXX系列,通过IIC总线读取和写入.由于写入时间比较长,需要通过延时来等待写入操作完成.这样的话串口接受的数据就没法在比较高的速度下接收了.
实际测试在波特率为600bps的情况下,这个模拟终端可以使用.
呵呵,这样的速度确实忒慢了....
最近一直在想解决的方法...
等到有新的更好的方案再重新编写程序.....

不多说了,先把图和部分代码贴上来...

有点不清晰, 左上角的是5V电源,提供给MCU
紧挨着的下面是USB-232转换电路,右边的就是模拟串口终端电路了....



设置波特率的画面:




波特率设置为600bps:




等待串口发送数据:






部分源代码:

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdbool.h>

#include "LCD1602.h"

/*        Define UART variable        */
//Baudrate value, 8 method for select. Fosc = 8MHz
#define Baud300 1
#define Baud600 2
#define Baud1200 3
#define Baud2400 4
#define Baud4800 5
#define Baud9600 6
#define Baud14400 7
#define Baud19200 8

/*         Define IIC Variable       */
#define IIC_ReStart() IIC_Start()
char PageTemp[17];
uint8_t TopPoint = 0;
uint8_t EndPoint = 0;
//Indicate whether the AT24C01 had full of data
bool CircularQueue = false;

/*        Define KeyScan Variable     */
uint8_t OldKeyNum = NULL;
uint8_t Key = NULL;

/*        Define Display Variable     */
char BufferBelow[16];//15 bit data, one bit to indicate end-point
char BufferAbove[16];
//Indicate how fast the data had been transmited
uint8_t BusyBit = 0;
//Indicate whether there have newest data
bool ChangeBit = false;
//Display up-arrow at the end of first line
#define PageupEnable() PutOneCharLCD(0,15,0x02)
//Display down-arrow at the end of the second line
#define PagedownEnable() PutOneCharLCD(1,15,0x03)
//Mark current read point
uint8_t ReadPoint = 0;

/*         Port   Initialization      */
void PortInit(void)
{
  DDRC &= ~((1<<PC5) | (1<<PC4));//IIC Port
  PORTC |= (1<<PC5) | (1<<PC4);
  DDRB &= ~((1<<PB1) | (1<<PB2) | (1<<PB3));//Key
  PORTB |= ((1<<PB1) | (1<<PB2) | (1<<PB3));
}

/*     Write up & down arrow to LCD   */
void WriteArrow(void)
{
  //Write up arrow to LCD CGRAM
  WriteCmdBF(0x40 | (0x02 << 3));
  WriteData(0x00);
  WriteData(0x04);
  WriteData(0x0E);
  WriteData(0x15);
  WriteData(0x04);
  WriteData(0x04);
  WriteData(0x04);
  WriteData(0x00);
 
  //Write down arrow to LCD CGRAM
  WriteCmdBF(0x40 | (0x03 << 3));
  WriteData(0x00);
  WriteData(0x04);
  WriteData(0x04);
  WriteData(0x04);
  WriteData(0x15);
  WriteData(0x0E);
  WriteData(0x04);
  WriteData(0x00);
 
  _delay_ms(10);
}

/*             Key Scan       */
uint8_t KeyScan(void)
{
  static uint8_t NewKeyNum;
  if((PINB&(1<<PB1)) == 0)
    {
    OldKeyNum = DOWN;
    }
  else if((PINB&(1<<PB2)) == 0)
    {
    OldKeyNum = UP;
    }
  else if((PINB&(1<<PB3)) == 0)
    {
    OldKeyNum = SEL;
    }
   
  //if key released, keyscan success
  if((PINB & (1<<PB1)) && (PINB & (1<<PB2)) && (PINB & (1<<PB3)))
    {
    NewKeyNum = OldKeyNum;
    OldKeyNum = NULL;
    return NewKeyNum;
    }
  else
    return NULL;
}

/*                                    */
/*               IIC                  */
/*                                    */
void IIC_Init(void)
{
  TWCR = 0x00;//Disable IIC while setting
  TWBR = 0x2A;//Set baud rate
  TWSR = 0x00;
  TWCR = 0x04;//Enable IIC
}

//Put 'start' on IIC bus
void IIC_Start(void)
{
  TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
  loop_until_bit_is_set(TWCR,TWINT);
}

//Put 'stop' on IIC bus
void IIC_Stop(void)
{
  TWCR |= (1<<TWINT) | (1<<TWSTO) | (1<<TWEN);
}

//Transmit data to slaver
void IIC_Write(uint8_t data)
{
  TWDR = data;
  TWCR = (1<<TWINT) | (1<<TWEN);
  loop_until_bit_is_set(TWCR,TWINT);
}

//Indicate Address & Length for read
void IIC_ReadPage(uint8_t Addr, uint8_t Bit)
{
  for(uint8_t i = 0;i<Bit;i++)
    PageTemp = IIC_ReadByte(Addr + i);

  PageTemp[Bit] = '\0';
}

/*                                    */
/*               UART                 */
/*                                    */
//only write UBRR
void SetBaudRate(uint8_t BaudRate)
{
  switch (BaudRate)
    {
    case Baud300:
      {
      UBRRL = 0x82;
      UBRRH = 0x06;
      PutStringLCD(1,0,"  300bps,ER:  0%");
      break;
      }
    case Baud600:
      {
      UBRRL = 0x40;
      UBRRH = 0x03;
      PutStringLCD(1,0,"  600bps,ER:  0%");
      break;
      }
    case Baud1200:
      {
      UBRRL = 0xA0;
      UBRRH = 0x01;
      PutStringLCD(1,0," 1200bps,ER:0.1%");
      break;
      }
    case Baud2400:
      {
      UBRRL = 0xCF;
      UBRRH = 0x00;
      PutStringLCD(1,0," 2400bps,ER:0.2%");
      break;
      }
    case Baud4800:
      {
      UBRRL = 0x67;
      UBRRH = 0x00;
      PutStringLCD(1,0," 4800bps,ER:0.2%");
      break;
      }
    case Baud9600:
      {
      UBRRL = 0x33;
      UBRRH = 0x00;
      PutStringLCD(1,0," 9600bps,ER:0.2%");
      break;
      }
    case Baud14400:
      {
      UBRRL = 0x22;
      UBRRH = 0x00;
      PutStringLCD(1,0,"14400bps,ER:0.8%");
      break;
      }
    case Baud19200:
      {
      UBRRL = 0x19;
      UBRRH = 0x00;
      PutStringLCD(1,0,"19200bps,ER:0.2%");
      break;
      }
    default: break;
    }
}

//Baud rate select
void BaudRateSel(void)
{
  //uint8_t Key = NULL;
  uint8_t BaudRate = 0;
 
  LCDispClear();
  PutStringLCD(0,0,"Set Baud Rate...");
 
  /* Disable UART while setting baud rate */
  UCSRB = 0x00;
  UCSRA = 0x00;
  //Write to UCSRC;Character size: 8 bit
  UCSRC = ((1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0));
 
  do{
    Key = KeyScan();
   
    switch (Key)
      {
      case UP:
        {
        if(BaudRate<8)
          BaudRate++;
        SetBaudRate(BaudRate);
        break;
        }
      case DOWN:
        {
        if(BaudRate>1)
          BaudRate--;
        SetBaudRate(BaudRate);
        break;
        }
      default: break;
      }
    _delay_ms(10);
    }while((Key != SEL) || (BaudRate == 0));
 
  /* Enable USART when setting finished  */
  //Receive interrupt Enable
  UCSRB = ((1<<RXCIE) | (1<<RXEN) | (1<<TXEN));
 
  PutStringLCD(0,0," UART Work at:  ");
}

void ShowVersion(void)
{
  LCDispClear();
  PutStringLCD(0,0,"Designed by lhy");
  PutStringLCD(1,0,"UARTerminal V1.0");
  _delay_ms(3000);
  PutStringLCD(1,0,"Pls press OK....");
  _delay_ms(100);
 
  do
    {
    Key = KeyScan();
    }while(Key != SEL);
}

路过

鸡蛋

鲜花

握手

雷人

评论 (0 个评论)