1
完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
扫一扫,分享给好友
可能觉得使用串口很简单,无非就是初始化GPIO,初始化串口。接着发送—检测是否成功。表面上看来是很简单的问题。然而,我要说的并不是这些。我要说的是volatile和中断向量表的问题。在其中配合一点gdb调试。 使用ringbuffer 这里的串口使用非缓冲发送,ringbuffer中断缓冲接收的方式。先来看看ringbuffer。ringbuffer是一个特殊的队列,FIFO。 struct ringbuffer{ uint8_t *bf; int len; int count; int putidx; /* read index and put index */ int getidx;};123456789struct ringbuffer对一个数组中的数据进行管理。数组的字节个数是len。更加详细的细节请大家尽情Google。写了一个宏,用来声明一个ringbuffer用来管理内存,准确的说叫做定义更好一些。 #define DECLARE_RB(name,len) uint8_t name##_buff[len]; struct ringbuffer name = { name##_buff,len,0,0,0 }1234提供的接口函数: #define rbcount(prb) ((prb)->count)#define rbfull(prb) ( (prb)->count==(rb)->len )#define rbempty(prb) ( (prb)->count==0 )/* if ringbuffer is full,return 0.else return 1 */int rbput(struct ringbuffer *prb,uint8_t add);/* if ringbuffer is empty,return -1.else return bf[tail] */int rbget(struct ringbuffer *prb);12345678rbput是往ringbuffer中添加一个数据。rbget是从ringbuffer中读取一个数据。相关的源代码: #include "ringbuffer.h"int rbput(struct ringbuffer *rb,uint8_t add){ int curidx=rb->putidx; if(rbfull(rb)) return 0; rb->bf[curidx]=add; rb->putidx=(curidx+1)%rb->len; rb->count++; return 1;}int rbget(struct ringbuffer *rb){ int result; int curidx=rb->getidx; if(rbempty(rb)) return -1; result=rb->bf[curidx]; rb->getidx=(curidx+1)%rb->len; rb->count--; return result;}12345678910111213141516171819202122串口中断+ringbuffer 在串口的初始化的时候,打开串口中断以及RXNE中断。在中断代码中将接受到的字符rbput到ringbuffer中。 /* USART interrupt handler */USART_Handler(){ if(USART_GetITStatus(USART,USART_IT_RXNE)==SET){ rbput(&rb_usart,USART_ReceiveData(USART)); }}1234567编写__io_getchar() __io_putchar()函数。用于发送和读取一个数据。 DECLARE_RB(rb_usart,USART_RD_BUF_LEN);int __io_putchar(int ch){ while(USART_GetFlagStatus(USART,USART_FLAG_TXE)!=SET); USART_SendData(USART,ch); return ch;}int __io_getchar(void){ signed char ch; while(rb_usart.count==0) continue; ch=rbget(&rb_usart); switch(ch) { case 'r':ch='n';break; case 0x1b:ch=' ';break; default: break; } /* echo it */ return __io_putchar(ch);}123456789101112131415161718192021222324当在使用minicom发送特殊的按键,比如Up,Down,Left,Right按键的时候,会发送以0x18开始的三个或者若干字符。对于这些,我们只显示0x18之后的字符。 由于使用minicom,putty一类的串口,发送的数据并不能回显。因此,要想有回显,只能在读取的时候进行回显。在中断中回显并不是一个好的方法,会占用一定的中断时间。因此我将回显放在__io_getchar函数中。 在主函数中一直读取字符 我们的主函数中什么也不做,一直在读取字符。由于读取的时候会有回显,所以不论我们按下什么按键,都会实时回显。 int main(void){ const char *str="Try to enter something...n"; const char *tmp=str; for(;*tmp!=' |