android uart串口如何使用中断,STM8S UART串口使用中断收发数据

原来调过STM8L的串口,逻辑简单,中断清晰,换成STM8S105K4后,虽然也是用STD库,除去函数名、宏名等语言层面的差异以外,中断处理方面也有些不一样的地方,特此记之。

和此篇【STM8L USART串口使用】结构相同,也是中断异步模式,但为调用方便起见,在调用层面改为同步。

(STM8S105K的MCU下,RX为PD6,RX为PD5。)

使用方面,感觉主要困扰就是中断名、使用场合和时机不明确、不清晰,这一点不如STM8L的定义清晰。

举例而言,开关中断用UART2_IT_RXNE_OR,清中断则用UART2_IT_RXNE。不能开关时用UART2_IT_RXNE,也不能清中断时用UART2_IT_RXNE_OR,否则STD库中参数合法assert断言,分分钟让程序挂起。

供大家参考。

以下是示例代码,为了和应用层更好的分离和代码通用化,设置了独立的UART的读写缓冲区,如果缓冲较大的情况下,请用@near置于分离数据区初始化。

另外虽然是中断驱动,考虑到绝大多数使用场景是同步的,设置了同步状态变量,读写函数中检测。改成中断的只需将状态变量的判断改成在应用面判断即可。

1. 读写缓冲和标识值定义

#define UART_BUF_SIZE 128

/* Read buffer */

uint8_t read_ok = 0;// 读完成flag

uint8_t read_idx = 0;

uint8_t read_len = 0;

@near uint8_t read_buffer[UART_BUF_SIZE];// 缓冲区设置较大的时候可用@near放置

/* Write buffer */

uint8_t writ_ok = 0;// 写完成flag

uint8_t writ_idx = 0;

uint8_t writ_len = 0;

@near uint8_t writ_buffer[UART_BUF_SIZE];  // 缓冲区设置较大的时候可用@near放置

2. 串口初始化

STM8S105K4只有一个串口,即UART2

int8_t uart_init(void)

{

// 串口参数请按需求修改

UART2_DeInit();

UART2_Init((uint32_t)38400,

UART2_WORDLENGTH_8D,

UART2_STOPBITS_1,

UART2_PARITY_NO,

UART2_SYNCMODE_CLOCK_DISABLE,

UART2_MODE_TXRX_ENABLE);

// 显式关中断(默认就是关)

// 注意:

// 读中断名字是UART2_IT_RXNE_OR,而不是UART2_IT_RXNE

// 写中断名字为UART2_IT_TXE

UART2_ITConfig(UART2_IT_RXNE_OR, DISABLE);

UART2_ITConfig(UART2_IT_TXE, DISABLE);

//串口使能

UART2_Cmd(ENABLE);

return 0;

}

3. 读写函数

// 写多个字节

void uart_send_n_byte(uint8_t* data, uint8_t len)

{

uint16_t count = 0;

UART2_ITConfig(UART2_IT_TXE, DISABLE);

// 准备写数据缓冲(从用户数据区复制到串口写缓冲、初始化索引值等)

memcpy(writ_buffer, data, len);

writ_idx = 0;

writ_len = len;

// 开写中断

UART2_ITConfig(UART2_IT_TXE, ENABLE);

while(!writ_ok) {  // 等待写完成(同步处理)

count++;

if( count >= 10000 ) {  // 简单的超时处理,不需要超时可以去除

writ_idx = 0;

writ_len = 0;

break;

}

}

writ_ok = 0;  // 写完成、重置写完成flag

return;

}

// 读多个字节

void  uart_read_n_byte(uint8_t* data, uint8_t len)

{

// 关读中断

UART2_ITConfig(UART2_IT_RXNE_OR, DISABLE);

// 清空读缓冲(重置读索引值即可)

read_idx = 0;

read_len = len;

// 开读中断

UART2_ITConfig(UART2_IT_RXNE_OR, ENABLE);

while(!read_ok); // 等待读操作完成(同步化处理)、添加超时处理可参照上述写操作

read_ok = 0;     // 写完成、重置写完成flag

memcpy(data, read_buffer, read_len);  // 复制数据到用户缓冲区

return;

}

4. 中断处理

INTERRUPT_HANDLER(UART2_TX_IRQHandler, 20)

{

// 写操作自动清中断,因此可以不用显式清中断

//UART2_ClearITPendingBit(UART2_IT_TXE);

// 从写缓冲中写出1字节

UART2_SendData8(writ_buffer[writ_idx++]);

// 全部写完、关写中断、置写完成标志(同步化处理)

if( writ_idx == writ_len ) {

UART2_ITConfig(UART2_IT_TXE, DISABLE);

writ_ok = 1;

}

}

INTERRUPT_HANDLER(UART2_RX_IRQHandler, 21)

{

// 读操作自动清中断,因此可以不用显式清中断

// 注意这里的中断名是RXNE,不是RXNE_OR

UART2_ClearITPendingBit(UART2_IT_RXNE);

// 读1字节

read_buffer[read_idx++] = UART2_ReceiveData8();

// 全部读完,关中断(UART2_IT_RXNE_OR),置读完成标志(同步化处理)

if( read_idx == read_len ) {

UART2_ITConfig(UART2_IT_RXNE_OR, DISABLE);

read_ok = 1;

}

}

5. 使用代码例

// 写2字节

uint8_t buf[32];

memset(buf, 0x00, sizeof(buf));

buf[0] = 0xCC;

buf[1] = 0xDD;

uart_send_n_byte(buf, 2);

// 简单读(必须读满24字节才返回)

memset(buf, 0x00, sizeof(buf));

uart_send_n_byte(buf, 24);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值