STM8S903K3基于ST Visual Develop开发串口接收中断示例
- 📌相关篇《STM8S903K3T6C基于ST Visual Develop开发串口数据收发示例》只针对单字符收发
📗UART中断请求
- 📓UART中断映射图
- 📑中断向量表有关串口中断号信息:
串口相关寄存器
- 状态寄存器(UARTx_SR)
- 数据寄存器(UART_DR)
⛳注意事项
- 设置波特率,必须注意以下几点:
- 必须先写BRR2
- BRR1存放的是分频系数的第11位到第4位,
- BRR2存放的是分频系数的第15位到第12位,和第3位到第0位
🌻接收中断数据转发功能实现
🔖将通过串口接收到的数据转发出去,对数据不做任何处理。
#include"stm8s903k3.h"
void CLK_Init(void)
{
// CLK_ECKR = 0x01; //开启外部时钟寄存器
// CLK_SWR = 0xb4; //HSE外部时钟源作为主时钟源
// CLK_CKDIVR = 0x00;//不分频
CLK_ICKR |= 0X01; //使能内部高速时钟 HSI
CLK_CKDIVR = 0x00; // 不分频,16M
// CLK_CKDIVR = 0x08; // 16M内部RC经2分频后系统时钟为8M
while(!(CLK_ICKR&0x02)); //HSI准备就绪
CLK_SWR = 0xE1;//HSI内部时钟源作为主时钟源(复位值)
}
void UART1_Init(void)
{
PD_DDR |= ( 1 << 5 ); //输出模式 TXD
PD_CR1 |= ( 1 << 5 ); //推挽输出
PD_DDR &= ~( 1 << 6 ); //输入模式 RXD
PD_CR1 &= ~( 1 << 6 ); //浮空输入
UART1_CR3 = 0x00;
/*disable LIN mode
-one stop bit
-disable SCK
*/
UART1_CR2 = 0x00;
/*disable TX interrupt
disable TX completion interrupt
disable RX interrupt
disable idle interrupt
disable TX and RX
没有发送断开帧
*/
UART1_CR3 = 0x00;
/*one start bit
eight data bits
wake up by idle bus
disable ECC and EEC interrupt
UART enable
*/
/* 波特率:9600 */
UART1_BRR2 = 0x02;//
UART1_BRR1 = 0x68;//
/* 波特率:115200 */
// UART1_BRR2 = 0x0b;
// UART1_BRR1 = 0x08;
UART1_CR2 |= 0x20;
UART1_CR2 |= 0x0C; //enable TX and RX
}
//char putchar(char c)
//{
// 发送一个字符 c 到UART1
// UART1_DR = c;
//等待发送完毕 */
// while (!(UART1_SR&0x40));
// return (c);
//}
void delay (unsigned int x)
{
unsigned int i,j;
for(i=x;i>0;i--)
for(j=300;j>0;j--);
}
//阻塞式发送函数
void SendChar( unsigned char dat )
{
/* 发送一个字符 c 到UART1 */
UART1_DR = dat;
/* 等待发送完毕 */
while (!(UART1_SR&0x40));
}
//发送字符串
void SendString( unsigned char* s )
{
while( '\0' != *s )
{
SendChar( *s );
s++;
}
}
//接收中断函数 中断号18
@far @interrupt void UART1_Handle( void )
{
while(!(UART1_SR&0x40));
RevByte = UART1_DR ;
UART1_DR = RevByte ;//转发出去
while(!(UART1_SR&0x40));
}
void main()
{
_asm("sim"); //disable all interrupt
CLK_Init();
UART1_Init();
_asm("rim"); //enable all interrupt
while(1);
}
- 🌿中断向量表源文件:
stm8_interrupt_vector.c
typedef void @far (*interrupt_handler_t)(void);
struct interrupt_vector {
unsigned char interrupt_instruction;
interrupt_handler_t interrupt_handler;
};
@far @interrupt void NonHandledInterrupt (void)
{
/* in order to detect unexpected events during development,
it is recommended to set a breakpoint on the following instruction
*/
return;
}
extern void _stext(); /* startup routine */
//extern @far @interrupt void TIM1_OVR_UIF(void);
extern @far @interrupt void UART1_Handle(void);
struct interrupt_vector const _vectab[] = {
{0x82, (interrupt_handler_t)_stext}, /* reset */
{0x82, NonHandledInterrupt}, /* trap */
{0x82, NonHandledInterrupt}, /* irq0 */
{0x82, NonHandledInterrupt}, /* irq1 */
{0x82, NonHandledInterrupt}, /* irq2 */
{0x82, NonHandledInterrupt}, /* irq3 */
{0x82, NonHandledInterrupt}, /* irq4 */
{0x82, NonHandledInterrupt}, /* irq5 */
{0x82, NonHandledInterrupt}, /* irq6 */
{0x82, NonHandledInterrupt}, /* irq7 */
{0x82, NonHandledInterrupt}, /* irq8 */
{0x82, NonHandledInterrupt}, /* irq9 */
{0x82, NonHandledInterrupt}, /* irq10 */
{0x82, NonHandledInterrupt}, /* irq11 TIM1*/
{0x82, NonHandledInterrupt}, /* irq12 */
{0x82, NonHandledInterrupt}, /* irq13 */
{0x82, NonHandledInterrupt}, /* irq14 */
{0x82, NonHandledInterrupt}, /* irq15 */
{0x82, NonHandledInterrupt}, /* irq16 */
{0x82, NonHandledInterrupt}, /* irq17 */
{0x82, UART1_Handle}, /* irq18 */
{0x82, NonHandledInterrupt}, /* irq19 */
{0x82, NonHandledInterrupt}, /* irq20 */
{0x82, NonHandledInterrupt}, /* irq21 */
{0x82, NonHandledInterrupt}, /* irq22 */
{0x82, NonHandledInterrupt}, /* irq23 */
{0x82, NonHandledInterrupt}, /* irq24 */
{0x82, NonHandledInterrupt}, /* irq25 */
{0x82, NonHandledInterrupt}, /* irq26 */
{0x82, NonHandledInterrupt}, /* irq27 */
{0x82, NonHandledInterrupt}, /* irq28 */
{0x82, NonHandledInterrupt}, /* irq29 */
};
🌼通过自定义传输协议,选择性处理接收数据
🚩此方法可以有针对性的对接收数据进行筛选。
📝示例代码
⛳通过对带有结束符且带换行符来判断数据接收完成,不过这样有一定的局限性。如果想实现对不定长数据完整接收需要添加更多的条件判断才行。
#include"stm8s903k3.h"
#include "string.h"
unsigned char cnt=0;
unsigned char RxBuffer[32];
unsigned char flag=0;
void CLK_Init(void)
{
// CLK_ECKR = 0x01; //开启外部时钟寄存器
// CLK_SWR = 0xb4; //HSE外部时钟源作为主时钟源
// CLK_CKDIVR = 0x00;//不分频
CLK_ICKR |= 0X01; //使能内部高速时钟 HSI
CLK_CKDIVR = 0x00; // 不分频,16M
// CLK_CKDIVR = 0x08; // 16M内部RC经2分频后系统时钟为8M
while(!(CLK_ICKR&0x02)); //HSI准备就绪
CLK_SWR = 0xE1;//HSI内部时钟源作为主时钟源(复位值)
}
void UART1_Init(void)
{
PD_DDR |= ( 1 << 5 ); //输出模式 TXD
PD_CR1 |= ( 1 << 5 ); //推挽输出
PD_DDR &= ~( 1 << 6 ); //输入模式 RXD
PD_CR1 &= ~( 1 << 6 ); //浮空输入
UART1_CR3 = 0x00;
/*disable LIN mode
-one stop bit
-disable SCK
*/
UART1_CR2 = 0x00;
/*disable TX interrupt
disable TX completion interrupt
disable RX interrupt
disable idle interrupt
disable TX and RX
没有发送断开帧
*/
UART1_CR3 = 0x00;
/*one start bit
eight data bits
wake up by idle bus
disable ECC and EEC interrupt
UART enable
*/
/* 波特率:9600 */
UART1_BRR2 = 0x02;//
UART1_BRR1 = 0x68;//
/* 波特率:115200 */
// UART1_BRR2 = 0x0b;
// UART1_BRR1 = 0x08;
UART1_CR2 |= 0x20;
UART1_CR2 |= 0x0C; //enable TX and RX
}
//char putchar(char c)
//{
// 发送一个字符 c 到UART1
// UART1_DR = c;
//等待发送完毕 */
// while (!(UART1_SR&0x40));
// return (c);
//}
void delay (unsigned int x)
{
unsigned int i,j;
for(i=x;i>0;i--)
for(j=300;j>0;j--);
}
//阻塞式发送函数
void SendChar( unsigned char dat )
{
/* 发送一个字符 c 到UART1 */
UART1_DR = dat;
/* 等待发送完毕 */
while (!(UART1_SR&0x40));
}
//发送字符串
void SendString( unsigned char* s )
{
while( '\0' != *s )
{
SendChar( *s );
s++;
}
}
//接收中断函数 中断号18
@far @interrupt void UART1_Handle( void )
{
char dataTmp ;
UART1_SR &= ~( 1 << 5 ); //RXNE 清零
dataTmp = UART1_DR;
if((0x0d != dataTmp)&&(0x0a != dataTmp))//换行符和回车符判断结束
{
RxBuffer[cnt++] = dataTmp;
}
else
{
RxBuffer[cnt] = '\0';
cnt=0;
flag = 1;
}
}
void main()
{
_asm("sim"); //disable all interrupt
CLK_Init();
UART1_Init();
_asm("rim"); //enable all interrupt
while(1)
{
if(flag == 1)
{
SendString(RxBuffer);
SendChar('\n');
memset(RxBuffer,0,sizeof(RxBuffer));
flag =0;
}
}
}
中断向量表源文件中的代码和上面的示例是相同的。