原创 STM32的LCD驱动及USART驱动

2008-7-23 00:42 5344 10 16 分类: MCU/ 嵌入式

        看了一下STM32 的英文文档,改出了LCD驱动及串口驱动程序,工程建立不多说了,看看这篇文章就一目了然:


http://blog.ednchina.com/likee/137492/message.aspx


 


*----------------------------------------------------------------------------*/


#include <stm32f10x_lib.h>                        // STM32F10x 库定义
#include <stdio.h>
#include "STM32_Init.h"                           // STM32 初始化


/*----------------------------------------------------------------------------
  Notes:
  The length of the receive and transmit buffers must be a power of 2.
  Each buffer has a next_in and a next_out index.
  If next_in = next_out, the buffer is empty.
  (next_in - next_out) % buffer_size = the number of characters in the buffer.
 *----------------------------------------------------------------------------*/
#define TBUF_SIZE   256      /*** Must be a power of 2 (2,4,8,16,32,64,128,256,512,...) ***/
#define RBUF_SIZE   256      /*** Must be a power of 2 (2,4,8,16,32,64,128,256,512,...) ***/


/*----------------------------------------------------------------------------
 *----------------------------------------------------------------------------*/
#if TBUF_SIZE < 2
#error TBUF_SIZE is too small.  It must be larger than 1.
#elif ((TBUF_SIZE & (TBUF_SIZE-1)) != 0)
#error TBUF_SIZE must be a power of 2.
#endif


#if RBUF_SIZE < 2
#error RBUF_SIZE is too small.  It must be larger than 1.
#elif ((RBUF_SIZE & (RBUF_SIZE-1)) != 0)
#error RBUF_SIZE must be a power of 2.
#endif


/*----------------------------------------------------------------------------
 *----------------------------------------------------------------------------*/
struct buf_st {
  unsigned int in;                                // Next In Index
  unsigned int out;                               // Next Out Index
  char buf [RBUF_SIZE];                           // 缓冲区
};


static struct buf_st rbuf = { 0, 0, };
#define SIO_RBUFLEN ((unsigned short)(rbuf.in - rbuf.out))


static struct buf_st tbuf = { 0, 0, };
#define SIO_TBUFLEN ((unsigned short)(tbuf.in - tbuf.out))


static unsigned int tx_restart = 1;               // 如果发送重新启动


/*----------------------------------------------------------------------------
  USART1_IRQHandler
  Handles USART1 global interrupt request.
 *----------------------------------------------------------------------------*/
void USART1_IRQHandler (void) {
  volatile unsigned int IIR;
  struct buf_st *p;


    IIR = USART1->SR;
    if (IIR & USART_FLAG_RXNE) {                  // 如果读中断
      USART1->SR &= ~USART_FLAG_RXNE;           // 则清除中断


      p = &rbuf;


      if (((p->in - p->out) & ~(RBUF_SIZE-1)) == 0) {
        p->buf [p->in & (RBUF_SIZE-1)] = (USART1->DR & 0x1FF);
        p->in++;
      }
    }


    if (IIR & USART_FLAG_TXE) {       //发送中断
      USART1->SR &= ~USART_FLAG_TXE;           // 清中断


      p = &tbuf;


      if (p->in != p->out) {
        USART1->DR = (p->buf [p->out & (TBUF_SIZE-1)] & 0x1FF);
        p->out++;
        tx_restart = 0;
      }
      else {
        tx_restart = 1;
  USART1->CR1 &= ~USART_FLAG_TXE;        // disable TX interrupt if nothing to send


      }
    }
}


/*------------------------------------------------------------------------------
  buffer_Init
  initialize the buffers
 *------------------------------------------------------------------------------*/
void buffer_Init (void) {


  tbuf.in = 0;                                    //清除缓冲区索引
  tbuf.out = 0;
  tx_restart = 1;


  rbuf.in = 0;
  rbuf.out = 0;
}


/*------------------------------------------------------------------------------
  SenChar
  transmit a character
 *------------------------------------------------------------------------------*/
int SendChar (int c) {
  struct buf_st *p = &tbuf;


                                                  //如果缓冲区满了。返回错误
  if (SIO_TBUFLEN >= TBUF_SIZE)
    return (-1);
                                                 
  p->buf [p->in & (TBUF_SIZE - 1)] = c;           //将数据加放发送缓冲氏
  p->in++;


  if (tx_restart) {                               //如果发送中断不能使,则使其能使
    tx_restart = 0;
 USART1->CR1 |= USART_FLAG_TXE;            // 允许发送中断
  }


  return (0);
}


/*------------------------------------------------------------------------------
  GetKey
  receive a character
 *------------------------------------------------------------------------------*/
int GetKey (void) {
  struct buf_st *p = &rbuf;


  if (SIO_RBUFLEN == 0)
    return (-1);


  return (p->buf [(p->out++) & (RBUF_SIZE - 1)]);
}



/*----------------------------------------------------------------------------
  MAIN function
 *----------------------------------------------------------------------------*/
int main (void) {
  int  i;
  char c;


  buffer_Init();                                  // init RX / TX buffers
  stm32_Init ();                                  // STM32 setup


  lcdWrStr("KEIL");
  for (i = 0; i < 10000; i++);                 // Wait for initial display
  printf ("\r\n Interrupt driven Serial I/O Example \r\n");


  lcdWrStr("->  ");
  while (1) {                                     // Loop forever
    printf ("Please press a key. ");
    c = getchar ();
    printf ("\r\n");
    printf ("You pressed just now is  '%c'.\r\n\r\n", c);


    lcdWrPos(&c, 3);


  } // end while
} // end main


 


#include <stm32f10x_lib.h>                              // stm32f10x definitions
#include "STM32_Reg.h"                                  // missing bit definitions



unsigned short lcdChar[128] = {
  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, //   0..9    unused
  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, //  10..19   unused
  0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, //  20..29   unused
  0x0000, 0x0000, 0x0000, 0x2002, 0x0012, 0x0000, 0xAE16, 0x0000, 0x0000, 0x0002, //  30..39   unused          
  0x0000, 0x0000, 0x7662, 0x2602, 0x2000, 0x0600, 0x0000, 0x1040, 0x99D4, 0x08C0, //  40..47   unused, '0', '1'          
  0x8784, 0x8C84, 0x0E90, 0x8E14, 0x8F14, 0x1044, 0x8F94, 0x8E94, 0x0000, 0x0000, //  '2'..'9', 58..59 unused          
  0x4040, 0x8600, 0x1020, 0x2494, 0x0000, 0x0F94, 0x8F10, 0x8114, 0x8F80, 0x8314, //  60..65   unused, 'A'..'E'          
  0x0314, 0x8D14, 0x0F90, 0x2002, 0x4880, 0x4350, 0x8110, 0x09F0, 0x49B0, 0x8994, //  'F'..'O'          
  0x0794, 0xC994, 0x4394, 0x8E14, 0x2006, 0x8990, 0x8990, 0x5990, 0x5060, 0x0160, //  'P'..'Y'         
  0x9044, 0x8114, 0x4020, 0x8884, 0x0000, 0x8000, 0x0010, 0x0F94, 0x8F10, 0x8700, //  'Z', 91..96 unused, 'a'..'c'          
  0x8F80, 0x8314, 0x0314, 0x8D14, 0x0F90, 0x2002, 0x4880, 0x4350, 0x8110, 0x09F0, //  'e'..'m'          
  0x49B0, 0x8F00, 0x0794, 0xC994, 0x0300, 0x8E14, 0x2006, 0x8990, 0x8990, 0x5900, //  'n'..'w'          
  0x5060, 0x0160, 0x9044, 0x0000, 0x2002, 0x0000, 0x0000, 0x0000};                //  'x'..'z', 123..127 unused          


 


unsigned short lcdBuffer[4] = {0, 0, 0, 0};             // LCD representation
unsigned int   lcdState     = 0;                        // write or clear
unsigned int   lcdWrState   = 0;                        // normal or inverted
unsigned int   lcdLine      = 0;                        // line 0..4



/*----------------------------------------------------------------------------
  clear LCD
 *----------------------------------------------------------------------------*/
void lcdClr (void) {
  int lineNr;


  for (lineNr = 0; lineNr < 4; lineNr++) {
    lcdBuffer[lineNr] = 0;
  }


}


/*----------------------------------------------------------------------------
  write a character to LCD position (0..3). Position 0 is left, 3 is right
 *----------------------------------------------------------------------------*/
void lcdWrPos (char* c, int pos) {
  int            lineNr;
  unsigned short cLcd;                                  // character coding for LCD


  cLcd = lcdChar[*c & 0x7F];                            // we only handel character 0..127


  for (lineNr = 0; lineNr < 4; lineNr++) {
    lcdBuffer[lineNr] = (lcdBuffer[lineNr] & ~(0xF<<(4*pos))) | (((cLcd>>(lineNr*4))& 0xF)<<(4*pos));
  }


}


/*----------------------------------------------------------------------------
  write a string to LCD position (0..3). max chars written is 4
 *----------------------------------------------------------------------------*/
void lcdWrStr (char* s) {
  int i;


  for (i = 0; i < 4; i++) {
    lcdWrPos (s+i, i);
  }


}



/*----------------------------------------------------------------------------
  TIM4_IRQHandler
  ticks every 2ms
 *----------------------------------------------------------------------------*/
void TIM4_IRQHandler(void)
{
  if (TIM4->SR & (1<<0)) {                              // UIF set?
//--------------------------------
  GPIOC->CRH &= 0xFFFF0000;
  GPIOC->CRH |= 0x00004444;                             // COM1..4 input floating
  GPIOC->CRH &= ~(0xF<<(4*(3-lcdLine)));
  GPIOC->CRH |=  (0x3<<(4*(3-lcdLine)));                // COMx    ouput push pull 50 MHz


  switch (lcdState){
    case 0:                                             // write state
      switch (lcdWrState) {
        case 0:                                         // write nomal data stat
          GPIOE->ODR  = lcdBuffer[lcdLine];             // write data
          GPIOC->BRR  = (1<<(8+(3-lcdLine)));           // COMx low


          lcdWrState = 1;                               // next state is write inverted data                      
        break;
        case 1:                                         // write inverted data state
          GPIOE->ODR  = ~lcdBuffer[lcdLine];            // write inverted data
          GPIOC->BSRR = (1<<(8+(3-lcdLine)));           // COMx high


          lcdWrState = 0;                               // next state is write normal data
          lcdLine = ((lcdLine+1) == 4) ? 0 : lcdLine+1; // handle next COM
        break;
      } // end switch (lcdWrState)


      lcdState = 1;                                     // next state is clearState
    break;


    case 1:                                             // clear state
      GPIOC->CRH &= 0xFFFF0000;
      GPIOC->CRH |= 0x00003333;                         // COM1..4 ouput push pull 50 MHz


      GPIOE->ODR  =  0x0000;                            // all Segments off
      GPIOC->BRR  = (0xF<<8);                           // all Lines off


      lcdState = 0;                                     // next state is writeState
    break;


  } // end switch (lcdState)
//--------------------------------
    TIM4->SR &= ~(1<<0);                                // clear UIF flag
  }


}


 


纯软件仿真结果如下:


5771a14d-a839-42fa-b0be-f1d520dcf20b.jpg


是不是很爽呢?呵呵。


 


 

文章评论6条评论)

登录后参与讨论

用户377235 2013-4-21 14:15

思路不错!

用户158443 2008-8-2 22:47

我正在找,谢谢!

用户154505 2008-8-1 17:04

一点技术含量也没有。

用户162278 2008-7-28 10:08

能不能把整个软件包发过来?

用户83468 2008-7-25 10:30

楼上写出这些的目的是什么?

daiqiumiao_806246054 2008-7-25 00:13

已经写出来了,详细见: http://blog.ednchina.com/likee/138832/message.aspx

用户83467 2008-7-24 17:10

keil的软件仿真功能这么强?能不能写个教程啊?我怎么找不到?
相关推荐阅读
daiqiumiao_806246054 2011-01-06 13:57
linux下yum代理设置
    我们在安装好linux后,经常会使用yum来更新系统,但是系统默认的代理是国外的,国内一般的网络不能访问,这里讲解具体做法,把代理换成国内的。attachment download      ...
daiqiumiao_806246054 2010-12-30 09:48
【转】ORACLE 10g下载地址
Oracle Database 10g Release 2 (10.2.0.1.0) Enterprise/Standard Edition for Microsoft Windows (32-bit...
daiqiumiao_806246054 2010-11-29 11:06
找工作的进来看
如下是我所有的开放性问题回答,希望对大家有帮助!1.      When choosing your first job/employer, what will you consider and wh...
daiqiumiao_806246054 2010-11-29 09:47
中长期规划---螺旋式上升方式修改完善职业之路
一、中长期职业发展的自我准备1、心态上随时做好准备 机会是给有准备的人的------“有准备”是你在做准备的过程中让“别人”认为你“有准备”!别人是包括你现在的老板和别的老板,以及你身边的人!他们对你...
daiqiumiao_806246054 2010-03-17 21:26
移动
分集方式传输损耗和距离关系光纤网络G网...
daiqiumiao_806246054 2010-03-17 09:40
GSM
特点  使用直观  GSM系统有几项重要特点:防盗拷能力佳、网络容量大、手机号码资源丰富、通话清晰、稳定性强不易受干扰、信息灵敏、通话死角少、手机耗电量低。  技术特点  1.频谱效率。由于采用了高效...
我要评论
6
10
关闭 站长推荐上一条 /2 下一条