沥沥小鱼 2024-04-30 00:03 采纳率: 45.5%
浏览 15
已结题

stm32 +51单片机 双机通信

T4:双机通信
使用一块 stm32 开发版和一块 51 开发版实现两块板子之间的通讯
(1)使用 51单片机的一个按键,当按键按下时,stm32上的一个 LED 灯点亮,5s后自动熄灭
(2)51单片机连接一个超声波传感器,使用 LCD 屏幕显示距离,当距离小于 10cm时,51单 片机蜂鸣器鸣叫报警,stm32 上的 LED 灯自动点亮;当距离大于 10cm,蜂鸣器停止鸣叫报警,LED 自动熄灭。
(3)stm32上按键按下,51单片机蜂鸣器鸣叫报警时间增加。
没有思路 可以提供大致代码思路吗

  • 写回答

7条回答 默认 最新

  • 码农阿豪@新空间 新星创作者: 前端开发技术领域 2024-04-30 00:04
    关注
    让阿豪来帮你解答,本回答参考chatgpt3.5编写提供,如果还有疑问可以评论或留言
    1. 使用51单片机按键,发送一个数据给stm32,stm32接收到数据后点亮LED灯,然后延时5秒,熄灭LED灯。 51单片机代码:
    #include<reg51.h>
    sbit key = P1^0; //按键连接在P1.0口
    void delay(unsigned int t){ //延时函数
        unsigned int i,j;
        for(i=0;i<t;i++){
            for(j=0;j<125;j++);
        }
    }
    void send_data(){ //发送数据的函数
        //使用串口通信发送数据给stm32
    }
    void main(){
        while(1){
            if(key == 0){ //按键按下
                send_data(); //发送数据
                delay(500); //延时,避免按键抖动
                while(key == 0); //等待按键松开
            }
        }
    }
    

    stm32代码:

    #include "stm32f10x.h"
    #define LED_PIN GPIO_Pin_0 //LED灯连接在GPIOA.0口
    #define USART_RX_PIN GPIO_Pin_10 //USART1接收引脚连接在GPIOA.10口
    #define USART_TX_PIN GPIO_Pin_9 //USART1发送引脚连接在GPIOA.9口
    void LED_On(){ //点亮LED灯的函数
        GPIO_WriteBit(GPIOA, LED_PIN, Bit_SET);
    }
    void LED_Off(){ //熄灭LED灯的函数
        GPIO_WriteBit(GPIOA, LED_PIN, Bit_RESET);
    }
    void USART1_Init(){ //USART1初始化函数
        USART_InitTypeDef USART_InitStructure;
        GPIO_InitTypeDef GPIO_InitStructure;
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
        //配置USART1引脚GPIO
        GPIO_InitStructure.GPIO_Pin = USART_TX_PIN;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
        GPIO_InitStructure.GPIO_Pin = USART_RX_PIN;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
        //配置USART1参数
        USART_InitStructure.USART_BaudRate = 115200;
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;
        USART_InitStructure.USART_StopBits = USART_StopBits_1;
        USART_InitStructure.USART_Parity = USART_Parity_No;
        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
        USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
        USART_Init(USART1, &USART_InitStructure);
        USART_Cmd(USART1, ENABLE);
    }
    void USART1_SendData(char data){ //发送单个字节的函数
        while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
        USART_SendData(USART1, data);
    }
    void EXTI0_IRQHandler(void){ //外部中断0的中断服务函数
        if(EXTI_GetITStatus(EXTI_Line0) != RESET){ //判断是否是外部中断0的触发
            LED_On(); //点亮LED灯
            USART1_SendData('A'); //发送数据给51单片机
            EXTI_ClearITPendingBit(EXTI_Line0); //清除中断标志位
        }
    }
    void delay_ms(uint32_t ms){ //毫秒级延时函数
        SysTick->LOAD = 9 * ms; //计数器重载值
        SysTick->VAL = 0; //清空计数器
        SysTick->CTRL |= (1 << 0); //开启计数器
        while((SysTick->CTRL & (1 << 16)) == 0); //等待计数器计满
    }
    void SysTick_Init(){ //SysTick初始化函数
        SysTick->CTRL = 0; //关闭计数器
        SysTick->LOAD = 0xFFFFFFFF; //设置重载值
        SysTick->VAL = 0; //清空计数器
        SysTick->CTRL |= (1 << 2); //选择外部时钟源
    }
    int main(void){
        GPIO_InitTypeDef GPIO_InitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;
        EXTI_InitTypeDef EXTI_InitStructure;
        USART1_Init(); //USART1初始化
        //配置LED灯引脚GPIO
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
        GPIO_InitStructure.GPIO_Pin = LED_PIN;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
        //配置PA0为中断口
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
        //配置为下降沿触发外部中断
        EXTI_InitStructure.EXTI_Line = EXTI_Line0;
        EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
        EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
        EXTI_InitStructure.EXTI_LineCmd = ENABLE;
        EXTI_Init(&EXTI_InitStructure);
        //配置外部中断0对应的NVIC
        NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x03;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
        SysTick_Init(); //初始化SysTick
        while(1){
            delay_ms(1000); //等待1s
            LED_Off(); //熄灭LED灯
        }
    }
    
    1. 使用51单片机超声波传感器测量距离,并发送数据给stm32,stm32接收到数据后判断距离是否小于10cm,如果小于10cm,点亮LED灯,蜂鸣器鸣叫报警;如果大于等于10cm,熄灭LED灯,蜂鸣器停止鸣叫报警。 51单片机代码:
    #include<reg51.h>
    sbit trig = P1^0; //超声波测距模块的trig引脚连接在P1.0口
    sbit echo = P1^1; //超声波测距模块的echo引脚连接在P1.1口
    sbit buzzer = P2^0; //蜂鸣器连接在P2.0口
    unsigned int distance; //保存测量到的距离
    void delay_us(unsigned int t){ //微秒级延时函数
        unsigned int i,j;
        for(i=0;i<t;i++){
            for(j=0;j<10;j++);
        }
    }
    void delay_ms(unsigned int t){ //毫秒级延时函数
        unsigned int i,j;
        for(i=0;i<t;i++){
            for(j=0;j<125;j++);
        }
    }
    void send_data(){ //发送数据的函数
        //使用串口通信发送数据给stm32
    }
    void measure_distance(){ //测量距离的函数
        unsigned int t;
        trig = 1; //触发一次脉冲
        delay_us(10);
        trig = 0;
        while(echo == 0); //等待从超声波模块返回的脉冲
        t = TH1 * 256 + TL1;
        distance = t / 58; //计算距离
    }
    void main(){
        while(1){
            measure_distance(); //测量距离
            send_data(); //发送数据
            delay_ms(50); //延时,避免测量频率过高
            //如果距离小于10cm,点亮LED灯,蜂鸣器鸣叫报警
            if(distance < 10){
                P1 = 0xFF; //点亮LED灯
                buzzer = 1; //鸣叫蜂鸣器
            }
            //如果距离大于等于10cm,熄灭LED灯,蜂鸣器停止鸣叫报警
            else{
                P1 = 0x00; //熄灭LED灯
                buzzer = 0; //停止鸣叫蜂鸣器
            }
        }
    }
    

    stm32代码: 和上一个问题的stm32代码相同。 3. stm32上的按键按下时,发送一个数据给51单片机,51单片机收到数据后将报警时间增加。我们可以在第二题的51单片机代码中加入一个变量,用来保存报警时间,每次收到stm32发送的数据时,将变量加上一个固定的值即可。 修改后的51单片机代码:

    #include<reg51.h>
    sbit trig = P1^0; //超声波测距模块的trig引脚连接在P1.0口
    sbit echo = P1^1; //超声波测距模块的echo引脚连接在P1.1口
    sbit buzzer = P2^0; //蜂鸣器连接在P2.0口
    unsigned int distance; //保存测量到的距离
    unsigned int alarm_time = 5000; //报警时间,初始化为5s
    void delay_us(unsigned int t){ //微秒级延时函数
        unsigned int i,j;
        for(i=0;i<t;i++){
            for(j=0;j<10;j++);
        }
    }
    void delay_ms(unsigned int t){ //毫秒级延时函数
        unsigned int i,j;
        for(i=0;i<t;i++){
            for(j=0;j<125;j++);
        }
    }
    void send_data(){ //发送数据的函数
        //使用串口通信发送数据给stm32
    }
    void measure_distance(){ //测量距离的函数
        unsigned int t;
        trig = 1; //触发一次脉冲
        delay_us(10);
        trig = 0;
        while(echo == 0); //等待从超声波模块返回的脉冲
        t = TH1 * 256 + TL1;
        distance = t / 58; //计算距离
    }
    void main(){
        while(1){
            measure_distance(); //测量距离
            send_data(); //发送数据
            delay_ms(50); //延时,避免测量频率过高
            //如果距离小于10cm,点亮LED灯,蜂鸣器鸣叫报警
            if(distance < 10){
                P1 = 0xFF; //点亮LED灯
                buzzer = 1; //鸣叫蜂鸣器
                delay_ms(alarm_time); //报警时间
            }
            //如果距离大于等于10cm,熄灭LED灯,蜂鸣器停止鸣叫报警
            else{
                P1 = 0x00; //熄灭LED灯
                buzzer = 0; //停止鸣叫蜂鸣器
            }
        }
    }
    

    stm32代码:

    #include "stm32f10x.h"
    #define LED_PIN GPIO_Pin_0 //LED灯连接在GPIOA.0口
    #define USART_RX_PIN GPIO_Pin_10 //USART1接收引脚连接在GPIOA.10口
    #define USART_TX_PIN GPIO_Pin_9 //USART1发送引脚连接在GPIOA.9口
    void LED_On(){ //点亮LED灯的函数
        GPIO_WriteBit(GPIOA, LED_PIN, Bit_SET);
    }
    void LED_Off(){ //熄灭LED灯的函数
        GPIO_WriteBit(GPIOA, LED_PIN, Bit_RESET);
    }
    void USART1_Init(){ //USART1初始化函数
        USART_InitTypeDef USART_InitStructure;
        GPIO_InitTypeDef GPIO_InitStructure;
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
        //配置USART1引脚GPIO
        GPIO_InitStructure.GPIO_Pin = USART_TX_PIN;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
        GPIO_InitStructure.GPIO_Pin = USART_RX_PIN;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
        //配置USART1参数
        USART_InitStructure.USART_BaudRate = 115200;
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;
        USART_InitStructure.USART_StopBits = USART_StopBits_1;
        USART_InitStructure.USART_Parity = USART_Parity_No;
        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
        USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
        USART_Init(USART1, &USART_InitStructure);
        USART_Cmd(USART1, ENABLE);
    }
    void USART1_SendData(char data){ //发送单个字节的函数
        while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
        USART_SendData(USART1, data);
    }
    void EXTI0_IRQHandler(void){ //外部中断0的中断服务函数
        if(EXTI_GetITStatus(EXTI_Line0) != RESET){ //判断是否是外部中断0的触发
            LED_On(); //点亮LED灯
            USART1_SendData('A'); //发送数据给51单片机
            EXTI_ClearITPendingBit(EXTI_Line0); //清除中断标志位
        }
    }
    void delay_ms(uint32_t ms){ //毫秒级延时函数
        SysTick->LOAD = 9 * ms; //计数器重载值
        SysTick->VAL = 0; //清空计数器
        SysTick->CTRL |= (1 << 0); //开启计数器
        while((SysTick->CTRL & (1 << 16)) == 0); //等待计数器计满
    }
    void SysTick_Init(){ //SysTick初始化函数
        SysTick->CTRL = 0; //关闭计数器
        SysTick->LOAD = 0xFFFFFFFF; //设置重载值
        SysTick->VAL = 0; //清空计数器
        SysTick->CTRL |= (1 << 2); //选择外部时钟源
    }
    void alarm_time_increase(){ //报警时间增加函数
        //发送数据给51单片机,让其将报警时间加上一个固定的值
    }
    int main(void){
        GPIO_InitTypeDef GPIO_InitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;
        EXTI_InitTypeDef EXTI_InitStructure;
        USART1_Init(); //USART1初始化
        //配置LED灯引脚GPIO
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
        GPIO_InitStructure.GPIO_Pin = LED_PIN;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
        //配置PA0为中断口
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
        //配置为下降沿触发外部中断
        EXTI_InitStructure.EXTI_Line = EXTI_Line0;
        EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
        EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
        EXTI_InitStructure.EXTI_LineCmd = ENABLE;
        EXTI_Init(&EXTI_InitStructure);
        //配置外部中断0对应的NVIC
        NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x03;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
        SysTick_Init(); //初始化SysTick
        while(1){
            delay_ms(1000); //等待
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(6条)

报告相同问题?

问题事件

  • 系统已结题 5月31日
  • 已采纳回答 5月23日
  • 创建了问题 4月30日