问题描述
我目前正在尝试在具有中断的STM32F103C8T6微控制器上实现串行通信。当我尝试分别发送字符ABCDE时,由我“ semi”编写的代码有效,但是我在台式机(Putty)上的终端应用程序正在显示我的一些遗漏字符。
我在终端模拟器中的结果 为什么几个字符重复?以及如何避免这种情况?
ABBCDEABCDEEABCDEABCCDEABCDEABBCDEABCDEEABCDEABCCDEABCDEAABCDEABCDDEABCDEABCCDEA
BCDEAABCDEABCDDEABCDEABBCDEABCDEEABCDEABCDDEABCDEABBCDEABCDEEABCDEABCCDEABCDEAAB
CDEABCDEEABCDEABCCDEABCDEAABCDEABCDDEABCDEABBCDEABCDEAABCDEABCDDEABCDEABBCDEABCD
请在下面喜欢我的代码
usart.c
#include "usart.h"
void usart_init(uint32_t Baudrate)
{
SystemCoreClockUpdate();
RCC->APB2ENR |=(RCC_APB2ENR_IOPAEN | RCC_APB2ENR_AFIOEN | RCC_APB2ENR_USART1EN);
GPIOA->CRH |= (GPIO_CRH_MODE9_0 | GPIO_CRH_MODE9_1);
GPIOA->CRH &= ~(GPIO_CRH_MODE10_0 | GPIO_CRH_MODE10_1);
GPIOA->CRH |= GPIO_CRH_CNF9_1;
GPIOA->CRH &= ~GPIO_CRH_CNF9_0;
GPIOA->CRH |= GPIO_CRH_CNF10_0;
GPIOA->CRH &= ~GPIO_CRH_CNF10_1;
USART1->BRR = (SystemCoreClock/Baudrate);
USART1->CR1 |= (USART_CR1_UE | USART_CR1_RE | USART_CR1_TE);
//USART1->CR1 |= USART_CR1_TXEIE;
NVIC_EnableIRQ(USART1_IRQn);
}
void buffer_init(void)
{
TxBuffer.in = 0;
TxBuffer.out = 0;
}
void putchar(unsigned char data)
{
__disable_irq();
struct Buffer_Struct *p = &TxBuffer;
p->Buffer[p->in & (BufferSize - 1)] = data;
p->in++;
if(tx_start)
{
tx_start = 0;
USART1->CR1 |=USART_CR1_TXEIE;
}
__enable_irq();
}
void USART1_IRQHandler(void)
{
struct Buffer_Struct *p;
if(USART1->SR & USART_SR_TXE)
{
p = &TxBuffer;
if(p->in != p->out)
{
USART1->DR = (p->Buffer[p->out & (BufferSize - 1)] & 0x1FF);
p->out++;
tx_start = 0;
}
}
}
usart.h
#ifndef USART_H
#define USART_H
#include "stm32f10x.h"
#include <stdbool.h>
#define BufferSize 64
struct Buffer_Struct {
unsigned int in;
unsigned int out;
unsigned char Buffer[BufferSize];
};
static struct Buffer_Struct TxBuffer = {0,};
static bool tx_start = 1;
void buffer_init(void);
void usart_init(uint32_t Baudrate);
void putchar(unsigned char data);
#endif
main.c
#include "stm32f10x.h"
#include "usart.h"
int main (void)
{
usart_init(9600);
while(1)
{
putchar('A');
putchar('B');
putchar('C');
putchar('D');
putchar('E');
}
}
解决方法
您的中断处理程序不正确。如果您不在其中放置任何内容,TXE始终为空,它将一直被调用。您需要在中断处理程序中禁用该中断。
我还喜欢使用编译器来完成这项工作,并在缓冲区大小为2的幂的情况下尝试使用位域
#define BufferSize 6
struct Buffer_Struct {
volatile unsigned int in : BufferSize;
volatile unsigned int out : BufferSize;
unsigned char Buffer[2 << BufferSize];
};
void putchar(unsigned char data)
{
TxBuffer.Buffer[TxBuffer.in] = data;
TxBuffer.in++;
USART1->CR1 |=USART_CR1_TXEIE;
}
void USART1_IRQHandler(void)
{
if(USART1->SR & USART_SR_TXE)
{
if(TxBuffer.in != TxBuffer.out)
{
USART1->DR = TxBuffer.Buffer[TxBuffer.out];
TxBuffer.out++;
if(TxBuffer.out == TxBuffer.in)
USART1->CR1 &= ~USART_CR1_TXEIE;
}
}
}
您的putchar函数也是错误的,因为它不检查缓冲区是否已满。
顺便说一句,在这种情况下,您不必禁用IRQ,因为您无需修改相同的变量。