利用定时器1产生全双工软件串口

news2024/10/7 2:25:13

代码;

/*
  《AVR专题精选》随书例程
  
  3.通信接口使用技巧

  项目:使用AVR定时器1和外中断实现全双工软件串口
  文件:softuart.c
  说明:软件串口驱动文件
        
  作者:邵子扬
  时间:2012年12月16日

*/
#include "softuart.h"

// 内部变量
struct TSOFTUART stUART;

// 软件串口初始化
void sfUART_init(void)
{
  // 设置IO状态
  PINDIR(sfUART_TXDIO, PIN_OUTPUT);
  PINSET(sfUART_TXDIO);
  PINDIR(sfUART_RXDIO, PIN_INPUT);
  PINSET(sfUART_RXDIO);
  
  // 内部变量初始化
  stUART.TXDcnt = 0;
  stUART.RXDcnt = 0;
  stUART.sfTXC = 0;
  stUART.sfRXC = 0;

  // 定时器初始化
  // CTC Mode
  // 分频比: 1
  OCR1A = 1;
  ICR1  = (F_CPU / sfBAUDRATE) - 1;
  TCCR1A = 0x00;
  TCCR1B = (1 << WGM13)|(1 << WGM12)|(1 << CS10);
  TIMSK = (1 << OCIE1A)|(0 << OCIE1B);

  // 外中断初始化
  // INT1
  // 允许外中断1,下降沿触发方式
  MCUCR = (1 << ISC11);
  sf_ENABLE_RXINT();

}

// 检查数据接收标志
char sfUART_RXC(void)
{
  return stUART.sfRXC;
}

// 检查数据发送完成标志
char sfUART_TXC(void)
{
  return stUART.sfTXC;
}

// 清除数据发送完成标志位
void sfUART_clrTXC(void)
{
  stUART.sfTXC = 0;
}

// 读取数据
char sfUART_getbyte(void)
{
  stUART.sfRXC = 0;
  return stUART.RXDBUF;
}

// 发送数据
void sfUART_sendbyte(char dat)
{
  stUART.TXDBUF = dat;
  stUART.sfTXC = 0;
  stUART.TXDcnt = 1;
}

// 软件串口数据发送服务程序
void sfUART_TXDsvr(void)
{
  switch(stUART.TXDcnt)
  {
    case 0:// 无数据
      return;
    case 1:// 发送起始位
      stUART.TXDcnt++;
      PINCLR(sfUART_TXDIO);
      break;
    case 2:// 发送数据
    case 3:
    case 4:
    case 5:
    case 6:
    case 7:
    case 8:
    case 9:
      if(stUART.TXDBUF & 0x01)
        PINSET(sfUART_TXDIO);
      else
        PINCLR(sfUART_TXDIO);
      stUART.TXDBUF = stUART.TXDBUF >> 1;
      stUART.TXDcnt++;
      break;
    case 10:// 发送停止位
      stUART.TXDcnt = 0;
      PINSET(sfUART_TXDIO);
      stUART.sfTXC = 1;
      break;
    default:
      stUART.TXDcnt = 0;
      return;

  }
}

// 软件串口数据接收服务程序
void sfUART_RXDsvr(void)
{
  switch(stUART.RXDcnt)
  {
    case 0:// 接收起始位
      stUART.RXDBUF = 0;
      stUART.RXDcnt++;
      break;
    case 1:// 接收数据位
    case 2:
    case 3:
    case 4:
    case 5:
    case 6:
    case 7:
    case 8:
      stUART.RXDBUF = stUART.RXDBUF >> 1;
      if(PININ(sfUART_RXDIO))
        stUART.RXDBUF |= 0x80;
      stUART.RXDcnt++;
      break;
    case 9:// 停止位
      stUART.sfRXC = 1;
      sf_RXD_STOP();
      GIFR |= (1<<INTF1);
      sf_ENABLE_RXINT();
      break;
    default:
      return;
  }
}

main.c

/*
  《AVR专题精选》随书例程
  
  3.通信接口使用技巧

  项目:使用AVR定时器1和外中断实现全双工软件串口
  文件:main.c
  说明:主程序,演示软件串口的使用方法
        
  作者:邵子扬
  时间:2012年12月16日

*/
#include "cfg.h"
#include "macromcu.h"
#include "softuart.h"

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

#define UBRRREG  (F_CPU / ( 8 * sfBAUDRATE ) - 1)

// 定时器1 COMPA中断服务程序
ISR(TIMER1_COMPA_vect, ISR_NOBLOCK)
{
  sfUART_TXDsvr();  // 软件串口发送服务程序
}

// 定时器1 COMPB中断服务程序
ISR(TIMER1_COMPB_vect, ISR_NOBLOCK)
{
  sfUART_RXDsvr();  // 软件串口接收服务程序
}

// 外中断服务程序
ISR(INT1_vect)
{
  sf_DISABLE_RXINT();  // 禁止外中断, 避免重复触发
  sf_RXD_START();      // 启动接收程序
}

int main(void)
{
  unsigned char tmp;

  PORTB = 0xFF;        // 仿真时, PB2(SS)需要设置为高电平
                       // 否则会出错. 实际使用时不需要

  sfUART_init();       // 初始化软件串口

  // 使用硬件串口作为对比
  UBRRH = UBRRREG / 256;
  UBRRL = UBRRREG % 256;
  UCSRA = ( 1 << U2X );
  UCSRB = ( 1 << TXEN );
  UCSRC = ( 1 << UCSZ1) | ( 1 << UCSZ0 );
  
  sei(); // 开中断


  for(;;)
  {

    if(sfUART_RXC())  // 接收到新数据
    {
      tmp = sfUART_getbyte(); // 读取数据
      UDR = tmp;              // 发送到硬件串口
      sfUART_sendbyte(tmp);   // 发送到软件串口
    }
    if(sfUART_TXC())  // 数据发送完成
    {
      sfUART_clrTXC();// 清除发送完成标志
    }

  }

  return 0;

}

仿真效果图:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1854954.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据库的概念-数据库、数据库管理系统、数据库系统、数据库管理员、数据库设计人员、开发管理使用数据库系统的人员

一、数据库&#xff08;DB&#xff09; 1、数据库就是存储数据的仓库&#xff0c;只不过这个仓库是在计算机存储设备上 2、严格的说&#xff0c;数据库是长期存储在计算机内、有组织的、统一管理的、可共享的相关数据的集合 3、数据库应是为一个特定目标而设计、构建并装入数…

阅读笔记:明朝那些事儿妖孽横行的宫廷

明朝那些事儿第四部看完了&#xff0c;合上书本给我印象比较深刻的文臣要数王守仁&#xff0c;不愧为明朝的军事家&#xff0c;思想家&#xff0c;文学家&#xff0c;教育家&#xff0c;他经过多年的思索、磨难、追求&#xff0c;终于有一天&#xff0c;在穷乡僻壤&#xff0c;…

PBR网络数据流量分流+NQA联动静态路由

一、实验目的&#xff1a; 企业有两个网段&#xff0c;业务1网段和业务2网段&#xff0c;拓扑图如下&#xff0c; 二、实验要求 pc1报文走左侧链路到达ar1&#xff0c;pc2报文走右侧链路到达ar1&#xff0c;且当ar2或者ar3发生故障时候&#xff0c;可以通过另一个设备到达ar1…

终极解决方案,传统极速方案,下载软件的双雄对决!

在数字资源日益丰富的今天&#xff0c;下载管理器成为了我们日常生活中不可或缺的工具。市场上两款备受欢迎的下载管理软件——Internet Download Manager&#xff08;IDM&#xff09;和迅雷11&#xff0c;它们以各自的特色和优势&#xff0c;满足了不同用户群体的需求。 软件…

应届毕业之本科简历制作

因为毕设以及编制岗位面试&#xff0c;最近好久没有更新了&#xff0c;刚好有同学问如何制作简历&#xff0c;我就准备将我自己制作简历的流程分享给各位&#xff0c;到此也算是一个小的结束&#xff0c;拿了工科学位证书毕业去做&#x1f402;&#x1f40e;了。 简历主要包含内…

Michael.W基于Foundry精读Openzeppelin第59期——Proxy.sol

Michael.W基于Foundry精读Openzeppelin第59期——Proxy.sol 0. 版本0.1 Proxy.sol 1. 目标合约2. 代码精读2.1 _delegate(address implementation) internal2.2 _implementation() internal && _beforeFallback() internal2.3 fallback() && receive() 0. 版本…

大电流一体成型电感CSEB1350系列,助力实现DC-DC转换器小尺寸、高效率

DC-DC转换器 , 转换器 , 科达嘉 DC-DC转换器作为一种电压转换装置&#xff0c;在电子产品、电源系统、工业控制、新能源等领域广泛应用。。。 DC-DC转换器作为一种电压转换装置&#xff0c;在电子产品、电源系统、工业控制、新能源等领域广泛应用。随着各行业用户对DC-DC转换器…

Mybatis plus:Wrapper接口

一、介绍 MyBatis-Plus 提供了一套强大的条件构造器&#xff08;Wrapper&#xff09;&#xff0c;用于构建复杂的数据库查询条件。Wrapper 类允许开发者以链式调用的方式构造查询条件&#xff0c;无需编写繁琐的 SQL 语句&#xff0c;从而提高开发效率并减少 SQL 注入的风险。 …

【MySQL】Linux中MySQL的使用及配置

一、字符集修改 1、MySQL8.0之前&#xff0c;字符集都默认是latin1&#xff0c;从MySQL8.0开始&#xff0c;字符集utf8mb4&#xff0c;这意味着&#xff0c;在默认情况下&#xff0c;MySQL8.0之前都是不支持中文的 # 查看字符集信息&#xff0c;主要是character_set_server和…

2024全国各地高考录取分数线一览表(含一本、二本、专科)

2024年高考录取分数线陆续公布&#xff0c;上大学网(www.sdaxue.com)为大家整理全国31个省市高考录取分数线汇总&#xff0c;包括本科批、专科批和特殊类招生控制分数线汇总&#xff0c;来看看你的省份多少分能上大学吧。 一、2024年全国高考录取线一览表 1、宁夏 一本线&…

3d隐藏模型为什么就不见了?---模大狮模型网

在3D建模和设计过程中&#xff0c;经常会遇到需要隐藏某些模型的情况。然而&#xff0c;有时候隐藏之后再也找不到这些模型了。这种情况可能让人感到困惑和沮丧。本文将探讨3D隐藏模型后“消失”的原因&#xff0c;并提供一些解决方法&#xff0c;帮助您更好地管理和查找隐藏的…

Vue的Router?一个小demo秒了

效果展示 正文 登录页 <template><div><div class"login"><h3>图书管理系统</h3><div class"user"><span>账号&#xff1a;</span><input type"text" v-model"user" /></…

监控 Promethus的监控告警Alertmanager、Grafana

Promethus的监控告警Alertmanager Alertmanager 介绍 Prometheus的一个组件&#xff0c;用于定义和发送告警通知&#xff0c;内置多种第三方告警通知方式&#xff0c;同时还提供了对Webhook通知的支持基于警报规则对规则产生的警报进行分组、抑制和路由&#xff0c;并把告警发…

Nginx基础概念和常用操作

文章目录 1. 安装、启动、连接2. 快速尝试部署网站3. 配置文件1. nginx.conf全局配置事件模块HTTP 模块性能优化建议 2. default.confserver 块基本设置日志设置根路径设置 4. 反向代理1. 模拟3个Web2. 链接 5. 负载均衡1. 加权轮询&#xff0c;Weighted Round Robin2. 最少连接…

【LeetCode刷题】232.用栈实现队列

目录 题目链接 图解思路 整体结构 实现过程 入队列 出队列 实现代码 MyQueue.h MyQueue.c stack.h stack.c test.c 题目链接 232. 用栈实现队列 - 力扣&#xff08;LeetCode&#xff09; 图解思路 整体结构 实现过程 入队列 插入数据时&#xff0c;插入到ist。…

SpringBoot使用AutoConfigure实现依赖库自动导入配置

我们知道导入配置有两种&#xff0c;一种是Value&#xff0c;一种是ConfigurationProperties&#xff0c;将对应的类标记为Component即可导入。但是被注解标识的类创建Bean有一个前提&#xff0c;只对启动类所在的包路径下的所有带有Component等注解的类才会创建Bean。如果我们…

Java智慧工地源码 5G智慧工地系统源码 使用SAAS部署 三维可视化管理,与一线生产过程相融合,集成数据后台,统一前端入口,呈现多方项目信息;

Java智慧工地源码 5G智慧工地系统源码 使用SAAS部署 三维可视化管理&#xff0c;与一线生产过程相融合&#xff0c;集成数据后台&#xff0c;统一前端入口&#xff0c;呈现多方项目信息; 智慧工地是指运用信息化手段&#xff0c;通过三维设计平台对工程项目进行精确设计和施工…

Java程序之素数问题

题目&#xff1a; 判断101-200之间有多少个素数&#xff0c;并输出所有素数。 程序分析&#xff1a; 判断素数的方法&#xff1a;用一个数分别去除2到sqrt(这个数)&#xff0c;如果能被整除&#xff0c;则表明此数不是素数&#xff0c;反之是素数。素数被利用在密码学上&#…

Kubernetes排错(七)-Pod 状态一直 ContainerCreating

查看 Pod 事件 $ kubectl describe pod apigateway-6dc48bf8b6-l8xrw -n cn-staging 异常原因 1&#xff09;no space left on device ... Events:Type Reason Age From Message---- ------ …

移远通信发布高性价比智能模组SC200P系列,赋能金融支付等行业智慧升级

近日&#xff0c;全球领先的物联网整体解决方案供应商移远通信宣布&#xff0c;为满足智慧金融、智能家居、智能穿戴、工业手持等消费和工业应用对高速率、多媒体、长生命周期等终端性能的需求&#xff0c;其正式推出基于紫光展锐UNISOC 7861平台的全新8核4G智能模组SC200P系列…