51单片机:STC89C52RC
#include "reg52.h"
#include "intrins.h"
#include "string.h"
sbit led1 = P3^7;
char buf[20]={0};
void Delay1000ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
i = 8;
j = 1;
k = 243;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void uart_init()
{
//设置SMOD=1
PCON = 0x10;
//设置串行通信方式1
SCON=0x50;
//设置定时器/计数器1定时、工作方式2
TMOD &=0x0F;
TMOD |= 0x20;
//设定定时常数
TL1=0xFD;
TH1=0xFD;
TR1=1;
ES=1;
}
void sendChar(char c)
{
SBUF=c;
while(!TI);
TI=0;
}
void sendString(char* str)
{
while(*str){
sendChar(*str);
str++;
}
}
void main()
{
EA=1;
uart_init();
while(1){
sendString("this is keil");
Delay1000ms();
}
}
void UART_Routine(void) interrupt 4
{
char tmp;
if(RI){
tmp = SBUF;
if(tmp == 'o'){
led1=1;
}else if(tmp == 'c'){
led1=0;
}
RI=0;
}
}
手册中提到的初始化示例
分析
- 看手册可以知道SCON是串行控制寄存器,PCON是波特率的寄存器,且可以知道SCON决定串行口的工作方式,同时波特率的设置与定时器1有关,所以需要初始化TMOD、PCON和SCON。
- 同时对于串口数据缓冲寄存器SBUF:每次只接收或者发送1个字节的数据,当发送完毕时,触发相应的接收或发送中断,同时由于接收和发送中断使用同一个中断,所以使用时需要进行判断,同时必须由软件清0
- 如果没有SBUF,则需要手动写,手册里面的解释是不断的发送地位数据,发送1位,数据移动。
stm32单片机:stm32f103c8t6
API
发送/接收函数
HAL_UART_Transmit()
:串口发送数据,使用超时管理机制HAL_UART_Receive()
:串口接收数据HAL_UART_Transmit_IT()
:串口中断模式发送HAL_UART_Receive_IT()
:串口中断模式接收
中断回调
HAL_UART_IRQHANDLER()
:串口中断处理函数HAL_UART_TxCpllback()
:发送中断回调函数HAL_UART_RxCpllback()
:接收中断回调函数
状态标记变量:USART_RX_STA
可以是16位也可以是32位,但最高位是用于接收完成标志,第二位是接收到0x0D标志
中断接收流程
重写printf映射
int fputc(int ch,FILE* f)
{
uint8_t tmp[1] = {ch};
HAL_UART_Transmit(&huart1,tmp,1,0xff);
return ch;
}
非中断示例
int fputc(int ch,FILE* f)
{
uint8_t tmp[1] = {ch};
HAL_UART_Transmit(&huart1,tmp,1,0xff);
}
//========================================================================
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_UART_Receive(&huart1,buf,99,100);
printf(buf);
memset(buf,'\0',strlen(buf));
}
中断示例
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART1){
//判断标志位最高位是否为1
if((UART1_RX_STA&0x8000) == 0){
//判断标志位第二位是否为1
if(UART1_RX_STA & 0x4000){
//判断是否接收完毕,也就是\n
if(re_buf==0x0a){
UART1_RX_STA |= 0x8000;
}else {
UART1_RX_STA=0;
}
}else {
//判断是否接收到了尾部,也就是\r
if(re_buf == 0x0d){
UART1_RX_STA |= 0x4000;
}else {
//0x3fff=0011 xxxx xxxx xxxx:就是能接收到数据的最多的个数
//&0x3fff就是防止数据溢出
buf[UART1_RX_STA&0x3FFF]=re_buf;
UART1_RX_STA++;
if(UART1_RX_STA>99){
UART1_RX_STA=0;
}
}
}
}
//中断接收完毕后,会自动关闭中断,所以这里需要重新打开
HAL_UART_Receive_IT(&huart1,&re_buf,1);
}
}
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
if(UART1_RX_STA & 0x8000){
printf("data:");
//UART1_RX_STA&0x3FFF就是不需要刷新缓冲区的原因
HAL_UART_Transmit(&huart1,buf,UART1_RX_STA&0x3FFF,0xff);
//这里可以看源码
while(huart1.gState != HAL_UART_STATE_READY);
printf("\r\n");
UART1_RX_STA=0;
}
printf("helloword\r\n");
HAL_Delay(1000);
}
会改变gState的状态,所以用while等待Transmit发送完毕