日志档案

发表于 2008-7-23 0:42:25

61

标签: USART  LCD  

STM32的LCD驱动及USART驱动

        看了一下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
  }

}

 

纯软件仿真结果如下:

是不是很爽呢?呵呵。

 

 

系统分类: 单片机   |   用户分类: STM32   |   来源: 原创   |   【推荐给朋友】   |   【添加到收藏夹】

    阅读(2559)    回复(7)  

投一票您将和博主都有获奖机会!

  • lkjh

    2008-7-24 17:10:41

    keil的软件仿真功能这么强?能不能写个教程啊?我怎么找不到?

  • likee

    2008-7-25 0:13:37

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

  • ednmanic

    2008-7-25 9:17:03

    C51中的关键字 http://www.liuguo.net 关键字 ;用 途 ; 说 明   AUTO ;存储种类说明 ;用以说明局部变量,缺省值为此   break ;程序语句 ;退出最内层循环   CASE ;程序语句 ;SWITCH语句中的选择项   char ;数据类型说明 ;单字节整型数或字符型数据   const ;存储类型说明 ;在程序执行过程中不可更改的常量值   continue ;程序语句 ;转向下一次循环   default ;程序语句 ;SWITCH语句中的失败选择项   do ;程序语句 ;构成do..while循环结构   double ;数据类型说明 ;双精度浮点数   else ;程序语句 ;构成if..else选择结构   enum ;数据类型说明 ;枚举   extern ;存储种类说明 ;在其他程序模块中说明了的全局变量   flost ;数据类型说明 ;单精度浮点数   for ;程序语句 ;构成for循环结构   goto ;程序语句 ;构成goto转移结构   if ;程序语句 ;构成if..else选择结构   int ;数据类型说明 ;基本整型数   long ;数据类型说明 ;长整型数   register ;存储种类说明 ;使用CPU内部寄存的变量   return ;程序语句 ;函数返回   short ;数据类型说明 ;短整型数   signed ;数据类型说明 ;有符号数,二进制数据的最高位为符号位   sizeof ;运算符 ;计算表达式或数据类型的字节数   STATIC ;存储种类说明 ;静态变量   struct ;数据类型说明 ;结构类型数据   swicth ;程序语句 ;构成SWITCH选择结构   typedef ;数据类型说明 ;重新进行数据类型定义   union ;数据类型说明 ;联合类型数据   unsigned ;数据类型说明 ;无符号数数据   void ;数据类型说明 ;无类型数据   volatile ;数据类型说明 ;该变量在程序执行中可被隐含地改变   while ;程序语句 ;构成while和do..while循环结构 附表1-1 ANSIC标准关键字 关键字 ;用 途 ;说 明   bit ;位标量声明 ;声明一个位标量或位类型的函数   sbit ;位标量声明 ;声明一个可位寻址变量   Sfr ;特殊功能寄存器声明 ;声明一个特殊功能寄存器   Sfr16 ;特殊功能寄存器声明 ;声明一个16位的特殊功能寄存器   data ;存储器类型说明 ;直接寻址的内部数据存储器   bdata ;存储器类型说明 ;可位寻址的内部数据存储器   idata ;存储器类型说明 ;间接寻址的内部数据存储器   pdata ;存储器类型说明 ;分页寻址的外部数据存储器   xdata ;存储器类型说明 ;外部数据存储器   code ;存储器类型说明 ;程序存储器   interrupt ;中断函数说明 ;定义一个中断函数   reentrant ;再入函数说明 ;定义一个再入函数   using ;寄存器组定义 ;定义芯片的工作寄存器 附表1-2 C51编译器的扩展关键字 附录二 AT89C51特殊功能寄存器列表(适用于同一架构的芯片) 符 号 ;地 址 ;注 释   *ACC ;E0H ;累加器   *B ;F0H ;乘法寄存器   *PSW ;D0H ;程序状态字   SP ;81H ;堆栈指针   DPL ;82H ;数据存储器指针低8位   DPH ;83H ;数据存储器指针高8位   *IE ;A8H ;中断允许控制器   *IP ;D8H ;中断优先控制器   *P0 ;80H ;端口0   *P1 ;90H ;端口1   *P2 ;A0H ;端口2   *P3 ;B0H ;端口3   PCON ;87H ;电源控制及波特率选择   *SCON ;98H ;串行口控制器   SBUF ;99H ;串行数据缓冲器   *TCON ;88H ;定时器控制   TMOD ;89H ;定时器方式选择   TL0 ;8AH ;定时器0低8位   TL1 ;8BH ;定时器1低8位   TH0 ;8CH ;定时器0低8位   TH1 ;8DH ;定时器1高8位 带*号的特殊功能寄存器都是可以位寻址的寄存 相关型号:74VHC08SJX IRFR014TR SSM2164S CY22392FC UC3823DWTR http://www.yule2000.com/74VHC08SJX_ic.htm http://www.yule2000.com/IRFR014TR_ic.htm http://www.yule2000.com/SSM2164S_ic.htm http://www.yule2000.com/CY22392FC_ic.htm http://www.yule2000.com/UC3823DWTR_ic.htm

  • cvb123

    2008-7-25 10:30:43

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

  • zhangyz002

    2008-7-28 10:08:36

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

  • wufudi002

    2008-8-1 17:04:26

    一点技术含量也没有。

  • zhangzd004

    2008-8-2 22:47:10

    我正在找,谢谢!