• gpio模拟串口通信


    1. 串口的传输协议

            UART使用异步模式工作,不需要时钟信号,其一般格式为:起始位+数据位+校验位+停止位。其中起始位1位,数据位5~8位,校验位0或1位,停止位1、1.5或2位。不过最常用的格式是1位起始位、8位数据位、没有奇偶校验、1位停止位,简记为8/N/1。

            8/N/1格式的时序图如下:

            空闲时数据线上规定为逻辑1。

            开始传输数据时先发送起始位,规定为逻辑0,接收端会检测这个下降沿,以便之后开始采样接收数据。

            起始位之后是数据位,规定先发送最低位,即LSB First。因为UART没有时钟信号,故使用波特率来确定每一位的长度,不过为保证检测的准确性,实际采样频率会高于波特率,一般每一位会进行若干次采样,取中间的采样值作为这一位的结果。

            奇偶校验位一般不使用。

            停止位一般使用1位,规定为逻辑1,除了表示传输结束外,停止位还可以起到时钟同步的作用。

            需要注意的是,这里的逻辑0并不一定是0V,这与使用的电平标准有关。对于TTL电平而言,逻辑0是0V,逻辑1是高电平(一般为3.3V或5V);对于RS-232电平而言,逻辑0是3V~15V,逻辑1是-3~-15V。

    2. gpio模拟串口通信

            以晶振频率11.0592M为时钟的芯片为例,实现波特率为9600BPS的串口通信(即传输一个位需要1/9600秒),定时时间=定时器计数值*机器周期=定时器计数值*12/晶振频率,现在定时时间为1/9600秒,定时器计数值=定时时间*晶振频率/12=110592/1152=96

            补充:机器周期表示执行一条cpu指令所需时间,时钟周期是1/晶振频率,一个机器周期一般由多个时钟周期组成,比如51单片机的一个机器周期由12个时钟周期组成。

    1. #define TM0_FLAG 0 //设传输标志位
    2. #define RXD P1_0 //通过P1_0 IO脚来模拟RXD功能引脚
    3. #define TXD P1_1 //通过P1_0 IO脚来模拟TXD功能引脚
    4. /* 计数器及中断初始化 */
    5. void S2INI(void)
    6. {
    7. TMOD |= 0x02; //计数器0,方式2
    8. TH0 = 0xA0; //预值为256-96=140,十六进制A0
    9. TL0 = TH0;
    10. TR0 = 0; //在发送或接收才开始使用
    11. TF0 = 0;
    12. ET0 = 1; //允许定时器0中断
    13. EA = 1; //中断允许总开关
    14. }
    15. /* 从串口读一个字符 */
    16. uchar RByte()
    17. {
    18. uchar Output = 0;
    19. uchar i = 8;
    20. TR0 = 1; //启动Timer0
    21. TL0 = TH0;
    22. WaitTF0(); //等过起始位
    23. //发送8位数据位
    24. while(i--)
    25. {
    26. Output >>= 1;
    27. if(RXD) Output |= 0x80; //先收低位
    28. WaitTF0(); //位间延时
    29. }
    30. while(!TM0_FLAG)
    31. {
    32. if(RXD) break; //收到结束位
    33. }
    34. TR0 = 0; //停止
    35. Timer0
    36. return Output;
    37. }
    38. /* 往串口写一个字节 */
    39. void WByte(uchar input)
    40. {
    41. uchar i = 8;
    42. TXD = (bit)0; //发送启始位
    43. WaitTF0();
    44. //发送8位数据位
    45. while(i--)
    46. {
    47. TXD = (bit)(input & 0x01); //先传低位
    48. WaitTF0();
    49. input = input >> 1;
    50. }
    51. TXD = (bit)1; //发送结束位
    52. WaitTF0();
    53. }
    54. /* 中断1处理程序 */
    55. void IntTimer0() interrupt 1
    56. {
    57. TM0_FLAG = 1; //设置标志位。
    58. }
    59. /* 查询传输标志位 */
    60. void WaitTF0( void )
    61. {
    62. while(!TM0_FLAG);
    63. TM0_FLAG = 0; //清标志位
    64. }

  • 相关阅读:
    基于单片机的红外无线测距仪
    PHP8中获取并删除数组中第一个元素-PHP8知识详解
    一文学会鉴别“套壳”ChatGPT模型
    HI3861学习笔记(26)——接入中国移动物联网开放平台OneNET
    该微信用户未开启“公众号安全助手”的消息接收功能,请先开启后再绑定
    ZMQ之自杀的蜗牛模式和黑箱模式
    Gnome-keyring如何进行密码的CRUD
    idea启动与jar包启动中使用resource资源文件路径问题总结
    VB.NET—窗体引起的乌龙事件
    Java基础:集合类之ArrayList、HashMap简介
  • 原文地址:https://blog.csdn.net/qq_41076734/article/details/125979074