本帖最后由 情场探花 于 2017-11-5 15:39 编辑
先说说我的环境:
KEIL MDK4.6, STM32F103C8T6,ST LINK
我想用 USART2 (PA2 和 PA3 )收发数据。目前调试阶段,把 PA2 和 PA3 短接。
症状:总是会多收一个 0x00,检查后发现接收缓冲区的指针 in, 就是 g_RxBuf.in 总是多加。按道理我发一个字节,它应该加1,实际增加了2,就是说收到了 2 个字节。由于是在办公室里,而且 TX 和 RX 都是短接的,所以也不像是是干扰。推测是初始化设置没弄好,特此请大侠指点一下。函数 SendChar() 是发送一个字节,我每次只发一个字节 0x55,然后就是接收了。结果收到的是 0x55 0x00
函数 GetKey() 是接收一个字节,如果缓冲区空则返回 -1.
#define CLOCK 72/8 //时钟频率72M
struct buf_st {
unsigned int in; /* Next In Index */
unsigned int out; /* Next Out Index */
char buf [RBUF_SIZE]; /* Buffer */
};
static struct buf_st g_RxBuf = { 0, 0, };
#define SIO_RBUFLEN ((unsigned short)(g_RxBuf.in - g_RxBuf.out))
static struct buf_st g_TxBuf = { 0, 0, };
#define SIO_TBUFLEN ((unsigned short)(g_TxBuf.in - g_TxBuf.out))
static unsigned int g_bTxRestart = 1; /* NZ if TX restart is required */
void USART2_Init(void)
{
int i;
RCC->APB2ENR |= ( 1UL << 0); /* enable clock Alternate Function */
AFIO->MAPR &= ~( 1UL << 3); /* clear USART2 remap */
RCC->APB2ENR |= ( 1UL << 2); /* enable GPIOA clock */
GPIOA->CRL &= 0xffff00ff;
GPIOA->CRL |= 0xb00; //PA2: output push-pull, Max. 50M speed
GPIOA->CRL |= 0x4000; //PA3: input floating
RCC->APB1ENR |= 0x020000; //¼´ RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
USART2->BRR = 0x1d4c;
USART2->CR1 = (( 1UL << 2) | /* enable RX */
( 1UL << 3) | /* enable TX */
( 1UL << 5) | /* enable RXNE Interrupt */
( 1UL << 7) | /* enable TXE Interrupt */
( 0UL << 12) ); /* 1 start bit, 8 data bits */
USART2->CR2 = 0x0000; /* 1 stop bit */
USART2->CR3 = 0x0000; /* no flow control */
for (i = 0; i < 0x1000; i++) __NOP(); /* avoid unwanted output */
NVIC_EnableIRQ(USART2_IRQn);
USART2->CR1 |= 0x2000; /* enable USART */
}
void USART2_IRQHandler (void) {
volatile unsigned int IIR;
struct buf_st *p;
IIR = USART2->SR;
if (IIR & USART_SR_RXNE) { /* read interrupt */
USART2->SR &= ~USART_SR_RXNE; /* clear interrupt */
p = &g_RxBuf;
if (((p->in - p->out) & ~(RBUF_SIZE-1)) == 0) {
p->buf [p->in & (RBUF_SIZE-1)] = (USART2->DR & 0x1FF);
p->in++;
}
}
if (IIR & USART_SR_TXE) {
USART2->SR &= ~USART_SR_TXE; /* clear interrupt */
p = &g_TxBuf;
if (p->in != p->out) {
USART2->DR = (p->buf [p->out & (TBUF_SIZE-1)] & 0x1FF);
p->out++;
g_bTxRestart = 0;
}
else {
g_bTxRestart = 1;
USART2->CR1 &= ~USART_SR_TXE; /* disable TX IRQ if nothing to send */
}
}
}
void buffer_Init (void) {
g_TxBuf.in = 0; /* Clear com buffer indexes */
g_TxBuf.out = 0;
g_bTxRestart = 1;
g_RxBuf.in = 0;
g_RxBuf.out = 0;
}
int SendChar (int c) {
int iii;
struct buf_st *p = &g_TxBuf;
if (SIO_TBUFLEN >= TBUF_SIZE) /* If the buffer is full */
return (-1); /* return an error value */
p->buf [p->in & (TBUF_SIZE - 1)] = c; /* Add data to the transmit buffer. */
p->in++;
if (g_bTxRestart) { /* If TX interrupt is disabled */
g_bTxRestart = 0; /* enable it */
USART2->CR1 |= USART_SR_TXE; /* enable TX interrupt */
}
return (0);
}
char GetKey (void)
{ int iii;
struct buf_st *p = &g_RxBuf;
if (SIO_RBUFLEN == 0)
return (0xff);
return (p->buf [(p->out++) & (RBUF_SIZE - 1)]);
}
|