看了一下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
}
}
纯软件仿真结果如下:
是不是很爽呢?呵呵。
用户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
用户83467 2008-7-24 17:10