原理图和流程图
流程图:
原理图:
串口通信
使用计时器1和串口中断
注:串口中断参考shihengrui同学的帖子
首先是 Timer1 和 uart0 的初始化:
void Timer1Init(){ CKCON0 |= CKCON0_T1M__SYSCLK; /** * Mode 2, 8-bit Counter/Timer with Auto-Reload */ TMOD = TMOD | TMOD_T1M__MODE2 | TMOD_CT1__TIMER | TMOD_GATE1__DISABLED; TCON &= ~TCON_TR1__BMASK; // STOP Timer1 TH1 = 0xFF-(SYSCLK/UART0_BAUD)/2; // 波特率设置卡了好久 TCON = TCON| TCON_TR1__RUN; // START Timer1 } void uartInit(){ // time1 Timer1Init(); // 9位失效 | 允许接收 // SCON0_MCE__MULTI_DISABLED | SCON0 = SCON0 | SCON0_REN__RECEIVE_ENABLED; P0MDIN = P0MDIN | P0MDIN_B4__DIGITAL | P0MDIN_B5__DIGITAL ; // 设置 P0.4 0.5 输入模式 P0MDOUT = P0MDOUT_B4__PUSH_PULL | P0MDOUT_B5__OPEN_DRAIN; // 设置 P0.4 0.5 输出模式 XBR0 = XBR0|XBR0_URT0E__ENABLED; IE = IE | IE_ES0__ENABLED; }
中断函数,把收到的消息存到结构体 UART_RX 中
#define RX_BUF_MAX_LEN 32 typedef struct { uint8_t rx_buff[RX_BUF_MAX_LEN]; uint8_t len; } URAT_RX; /******************************************************************************* Function: // UART0_IRQn Description: // 串口0中断函数 Input: // 无 Return: // 无 *******************************************************************************/ SI_INTERRUPT(UART0_ISR, UART0_IRQn) { if (SCON0_TI == 1) // Check if transmit flag is set { tx_flag = 1; SCON0_TI = 0; // Clear interrupt flag } if (SCON0_RI == 1) { uart0.rx_buff[uart0.len++] = SBUF0; if (uart0.len == RX_BUF_MAX_LEN) uart0.len = 0; uart0.rx_buff[uart0.len]='\0'; SCON0_RI = 0; } }
发送数据和清空数据(其实就是len置0,数据写结束符 \0)
void uartSend(char *buf) { uint8_t count = 0; SCON0_TI = 0; while (buf[count] != '\0') { tx_flag = 0; SBUF0 = buf[count]; while (!tx_flag) ; count++; } for(count=0; count<uart0.len; count++) { tx_flag = 0; SBUF0 = uart0.rx_buff[count]; while (!tx_flag) ; } } void uartClearBuf(){ uart0.len=0; uart0.rx_buff[0]='\0'; }
消息处理函数,用了回调,就可以根据不同消息来进行不同的响应
/** * 消息处理函数 * @param str * @param func * @param all 类型,1则全等,0则模糊查询 */ void msgHandler(char *str, void(*func)(void), char all){ bool flag = false; if(all==1){ flag = strcmp(uart0.rx_buff, str)==0; }else{ flag = strstr(uart0.rx_buff, str)!=NULL; } if(flag){ func(); uartClearBuf(); } } void funcLed0(){ P1_B4 = 0; } void funcLed1(){ P1_B4 = 1; }
消息函数使用示例如下: 当消息内容匹配为 LED1/LED0 时点亮和熄灭板载LED (进行串口点灯),当消息内容里面存在 clear 字符串时,清空消息
msgHandler("LED1", funcLed1, 1); msgHandler("LED0", funcLed0, 1); msgHandler("clear", uartClearBuf, 0);
驱动步进电机
使用 ULN2003驱动板来驱动步进电机28BYJ-48,使用四个IO口发送步进数据即可
void motorInit(){ P1MDIN = P1MDIN | P1MDIN_B0__DIGITAL | P1MDIN_B1__DIGITAL | P1MDIN_B2__DIGITAL | P1MDIN_B3__DIGITAL; // 设置 P1.0~3 输入模式 P1MDOUT = P1MDOUT | P1MDOUT_B0__PUSH_PULL | P1MDOUT_B1__PUSH_PULL | P1MDOUT_B2__PUSH_PULL | P1MDOUT_B3__PUSH_PULL; // 设置 P1.0~3 输出模式 } void motorStep(uint8_t step, uint8_t dir) { uint8_t temp=step; if(dir==0) //如果为逆时针旋转 temp=7-step;//调换节拍信号 switch(temp)//8 个节拍控制:A->AB->B->BC->C->CD->D->DA { case 0: P1_B0=1;P1_B1=0;P1_B2=0;P1_B3=0;break; case 1: P1_B0=1;P1_B1=1;P1_B2=0;P1_B3=0;break; case 2: P1_B0=0;P1_B1=1;P1_B2=0;P1_B3=0;break; case 3: P1_B0=0;P1_B1=1;P1_B2=1;P1_B3=0;break; case 4: P1_B0=0;P1_B1=0;P1_B2=1;P1_B3=0;break; case 5: P1_B0=0;P1_B1=0;P1_B2=1;P1_B3=1;break; case 6: P1_B0=0;P1_B1=0;P1_B2=0;P1_B3=1;break; case 7: P1_B0=1;P1_B1=0;P1_B2=0;P1_B3=1;break; } }
红外遥控
本打算使用外部中断来接收信号,处理不同按键数据,不小心把线碰掉,重新插上接反了,烧了接收器。(这仅有的接收器还是一块51学习板上拔的)后续工作无法进行了,只能等年后买接收器了。
先把外部中断代码贴上来
void iredInit(){ P0_B3=1; P0MDOUT |= P0MDOUT_B3__SHIFT; P0MDIN |= P0MDIN_B3__DIGITAL; // 控制位:int0 边沿触发 TCON |= TCON_IT1__EDGE; // 低电位有效 | 设置P0.3为int0的中断IO IT01CF = IT01CF_IN1PL__ACTIVE_LOW | IT01CF_IN1SL__P0_3; IE |= IE_EX1__ENABLED; } SI_INTERRUPT(INT1_ISR, INT1_IRQn) { P1_B4 = !P1_B4; }
效果就是,遥控有按键,P0.3收到中断信号,板载LED会亮灭切换。
打赏帖 | |
---|---|
【Zephyr】MCXN947 Zephyr 开发入门适配shell被打赏20分 | |
【我要开发板】6.联合MATLAB记录数据被打赏50分 | |
【瑞萨RA2E1开发板】:使用ADC功能实现位移传感器采集方案被打赏20分 | |
【nRF7002DK】基于sht30的温湿度计被打赏20分 | |
【nRF7002DK】日志打印被打赏20分 | |
【换取手持示波器】RGB屏幕移植ARM-2D库被打赏35分 | |
【分享开发笔记,赚取电动螺丝刀】分享一下如何解决瑞萨RA2E1使用printf编译报错问题被打赏27分 | |
rtthread硬件加密-5hash加密分析被打赏10分 | |
【换取手持示波器】Mongoose 零代码创建网页仪表盘被打赏33分 | |
【分享开发笔记,赚取电动螺丝刀】基于.Net6.0 WPF简单做一个MQTT收发小工具被打赏24分 |