历史上的今天
返回首页

历史上的今天

今天是:2025年07月30日(星期三)

正在发生

2018年07月30日 | PIC单片机精通_A/D转换&异步串口通讯实例与详解

2018-07-30 来源:eefocus

1.前言


串口通信这个话题对于很多做机电一体化、机器人控制等系统协调的同学,根本不陌生。计算机软件(编程技术),近些年飞速发展。尤其是以机器学习、仿生控制、大数据为代表的AI行业。但是,软件及算法永远不会停留在“数学”这个圈圈里,我们需要把它推向工程,推向实践。这样作为软硬件交流的“握手协议”的重要性就不言自明。

这一片主要介绍比较完整的串口通信代码,具体为PIC16F876a与上位机进行数据交流的事。这个过程包括了模拟信号到数字信号的转换、模拟信号采样率、通信协议、计算机软件、算法设计等一系列有趣的问题。有了硬件的数据采集模块,我们就可以在软件和算法上做更多的创新工作!

本篇主要集中讨论以下问题:

1.定时器初值该如何计算?

2.PIC系列单片机的中断优先级是如何设置的?

3.AD采集模块的数据存储与发送原理是什么?

4.左对齐、右对齐的优势与劣势的缺点又是什么?

2.程序与代码详解


 /**************************************************

**Author: Shen Chunxu  All Rights Reserved!

**Tsinghua University 2016-11-20

**ad module + usart module

**************************************************/

#include

__CONFIG(0x3ffa); 

 

#define BAUD 9600     

#define FOSC 9216000L 

#define BaudInitVal ((int)(FOSC/(16UL * BAUD) -1)) //高速情况下设定波特率初始值

 

#define RX_PIN TRISC7  //定义数据通讯端口

#define TX_PIN TRISC6

 

unsigned char Rece_flag;  //初始化,串口接受标志

unsigned char Time_flag;  //初始化,时钟标志

unsigned int adResult;   //保存ad转换结果

 

void InitAdusart(void);  //初始化AD模块、串口模块

void InitTimer(void);    //定时器1初始化

 

void main()

{

INTCON = 0x00;  //清空中断控制器

RX_PIN = 1;     //端口RX TX初始化

TX_PIN = 0;

 

InitAdusart();  //串口、AD初始化

InitTimer(); //定时器初始化,预装初值

 

//中断控制

GIE  = 1; //允许全局中断

PEIE = 1; //允许外围触发中断

RCIE = 1; //开启串口接收触发中断

TMR1IE = 1;      //开启定时器溢出中断

TMR1IF = 0;     //定时器溢出标志位初始化

RCIF = 0;       //串口接收标志位初始化

TMR1ON = 1; //开启定时器Timer1

while(1)

{//'S'对应上位机“开始”按键

if( Rece_flag == 'S')

{

if( Time_flag == 1)

{

ADGO=1;       //开始ad转换采集

while( ADGO==1 ) 

continue;   //等待转换采集完毕

//adResult = (unsigned int)ADRESH<<8 + ADRESL; // 右对齐10-bit

//adResult = (unsigned int)(ADRESH<<6 + ADRESL>>2); //简化运算 10bit->8bit

adResult = ADRESH;

//////一次串口发送过程

TXREG = adResult; //把AD结果送到发送缓存区

while( TRMT == 0)   //等待发送完毕

continue;

///////装入初值,提供足够的采样时间

Time_flag = 0;  

TMR1L=0xc0;     //定时50ms

TMR1H=0xc7;

}

}

}

}

 

//上位机发送信号触发中断

void interrupt Serve(void)

{

if( RCIF )  //串口接收中断,优先级最高

{

RCIF = 0; //软件清空中断标志位

Rece_flag = RCREG;

if('E' == Rece_flag) //对应上位机“结束”按键

{

//给PC机反馈信号“END”

TXREG = 'E';

while( TRMT == 0 ) 

continue; //检验发送是否结束

TXREG = 'N';

while(TRMT==0)

continue;

TXREG = 'D';

while(TRMT==0)

continue; 

}

else if( 'S' == Rece_flag )

{

//给PC机反馈信号“OK”

TXREG = 'O';

while(TRMT==0) 

continue;

TXREG = 'K';

while(TRMT==0) 

continue;

else //其他信号不响应

{ ; }

}

else if( TMR1IF ) //定时器溢出串口接收中断,优先级次之,主要控制(AD转换时间+串口发送时间)

{

TMR1IF = 0; //软件清空定时器中断标志位

Time_flag = 1;

}

}

 

// 串口、AD模块

void InitAdusart(void)

{

    //串口模块初始化

SPBRG = BaudInitVal; //设定波特率

RCSTA=0x90; //1-0-0-1-0-0-0-0=串口工作-8位接收-禁止单字节-连续-空-无帧检错-无溢出检错-无奇偶校验

TXSTA=0x24; //0-0-1-0-0-1-0-0=异步不设置时钟-8位发送-允许发送-异步-空-高速-TSR为空-无奇偶校验

//AD模块初始化

ADCON0=0x49;     //01-001-0-0-1=FOSC/16-AN1-不转换-空-上电

//ADCON1=0xc9; //1-1-00-1001=右对齐-FOSC/16-空-VDD+VSS参考电压(AN0~AN5)

ADCON1=0x49; //0-1-00-1001=左对齐-FOSC/16-空-VDD+VSS参考电压(AN0~AN5)

}

//Timer初始化

void InitTimer()

{

T1CON=0x30; //00-11-0-0-0-0=空-8分频-禁止起振-定时器模式-内部时钟-暂时不开启

TMR1L=0xc0;         //定时50ms

TMR1H=0xc7;

}

3.注意事项


1.PIC系列仅仅提供提供了一个中断服务程序,并没有提供中断优先级寄存器。我们要向实现多级中断有序进行,这里我提供了一种“分支语句+中断标志位”结合的方法,实验证明,该方法确实能够做到中断优先级的管控!这里还是要提示一点,一如中断,首先要清空中断标志寄存器!!!这很重要!

2.关于定时器的初值问题。这里仅仅就PIC16F876a的16位Timer1而言。计算如下:  

定时时间(s) = 分频比*(2^16 - 处置)*指令周期

指令周期 = 4*时钟周期     时钟周期 = 1/晶振频率

切记!看好自己的晶振频率在计算。

4.思考与总结


1.利用定时器的精准定时功能,实现周期采样的控制。

2.采用A/D左对齐的方式,使得数据读取更方便。

3.多个分支或者多个条件控制时,提倡采用“设标”的方法进行程序设计!这可以大大提高程序的可读性。在这里,讲一下设标的心得,建议将标志位设为静态变量或者全局变量,这可以大大提高程序的健壮性!


推荐阅读

史海拾趣

Conditioning Semiconductor Devices Corp公司的发展小趣事

Conditioning Semiconductor Devices Corp(简称CSDC)起初是一家小型半导体公司,专注于研发低功耗的芯片技术。随着智能设备的普及,市场对节能型半导体的需求激增。CSDC通过不断的研发投入,成功开发了一种全新的低功耗技术,显著降低了设备的能耗,迅速在市场上获得认可,从而实现了业务的快速增长。

意华(CZT)公司的发展小趣事

自1995年成立以来,意华(CZT)始终秉持“诚信”的合作态度和“创新”的发展思路。在公司初创阶段,面对激烈的市场竞争,意华坚持高质量的产品和服务,赢得了客户的信赖。同时,公司不断投入研发,推出了一系列具有创新性的电子产品和连接器,迅速在市场上树立了良好的口碑。

Custom Electronics Inc公司的发展小趣事

在全球环保意识的日益增强下,CEI积极响应国家节能减排的号召,将环保理念融入企业的生产和经营中。公司引进先进的环保设备和技术,优化生产工艺流程,减少能源消耗和废弃物排放。同时,CEI还倡导绿色消费和循环经济理念,推动电子行业的绿色发展和可持续发展。

请注意,以上故事仅为基于一般情况和假设情境的概述,并非CEI公司的实际发展历程。如有需要,建议查阅相关文献资料或咨询行业专家以获取更准确的信息。

Bedford Opto公司的发展小趣事

随着国内市场的饱和,Bedford Opto公司开始寻求国际化扩张的机会。通过与国外知名企业的合作,公司成功打入国际市场,并获得了更多的业务机会。同时,公司还积极参与国际技术交流与合作,不断提升自身的技术水平和创新能力。

G-Two Inc公司的发展小趣事

背景:随着全球光伏产业的快速发展,对光伏胶膜的需求急剧增加。

发展:福斯特抓住市场机遇,不断扩大产能,完善产品品类,提高产品质量。同时,公司还积极开拓国际市场,与全球多家知名光伏组件企业建立了长期合作关系。

成果:到2021年,福斯特的光伏胶膜全球市占率超过50%,成为全球光伏胶膜行业的龙头企业。

强盛电子(AEC)公司的发展小趣事

随着环保意识的日益增强,AEC积极响应国家绿色发展的号召,将环保理念融入企业的日常运营中。公司投入大量资金进行环保技术的研发和应用,推动生产过程的绿色化、低碳化。同时,AEC还积极参与社会公益活动,为保护环境、促进可持续发展贡献了自己的力量。

问答坊 | AI 解惑

请教:在vc++下能通过,移植到evc下提示链接错误!

HTTPServer.obj : error LNK2019: unresolved external symbol \"public: __cdecl std::_Lockit::~_Lockit(void)\" (??1_Lockit@std@@QAA@XZ) referenced in function \"public: __cdecl std::_Tree::~_Tree(vo id)\" (??1?$_Tree@V?$basic_string ...…

查看全部问答>

pci的bar问题

请问高手们,怎样通过pci的配置寄存器中的bar读取的值,来获取映射到io或者memory的地址?bar是一个32位的寄存器。。。…

查看全部问答>

IDE转SATA时,端口怎么初始化?

我想利用IDE转SATA和SATA转IDE 2种卡实现并/串高速数据传输! 有2个地方都是并口,40M速度,想利用IDE转SATA卡先并--串行,然后用SATA转IDE卡再把串--并行,实现近距离数据传输。实验时距离不超过30cm, 但用示波器就是看不到数据传过来。此方案若 ...…

查看全部问答>

mxchip制作的中文手册不厚道

                                 mxchip制作的中文手册排版上太浪费空间,本来一页能写下的东西洋洋洒洒写了两页多,还不让编辑,要是把一本stm32固 ...…

查看全部问答>

请教香水城

VTarget = 3.352V Info: TotalIRLen = 9, IRPrint = 0x0011 ***JLink Error: Wrong ROM location (15:2). Expected 0xE00FF003, Found 0x14 ...…

查看全部问答>

寻找测量物体竖直高度的传感器

公司的垂直连续电镀线上面需要安装一个能测量PCB板的高度的传感器,PCB板子是垂直悬吊起来的,排成一排,在水平方向运动…

查看全部问答>

FCI连接器已解决FFC/FPC方案

      FCI已推出高速I/O接口的完整产品线。然而随着科技的不断进步,由FCI公司生产的新型SFGL系列( 0.4毫米间距和0.9毫米高度)FPC后翻式ZIF连接器含有各种微间距后翻执行机构系列,它们就是目前的间距0.5毫米、高度0.9毫米( ...…

查看全部问答>

M430 UART0 接收数据

最近在研究430 看到有人写的一段代码,为了接收GPS的数据,使用串口中断接收,部分代码如下: if(global_temp_data_num==0)   //获取\"GG\"标志         {           if ...…

查看全部问答>

keil5里添加文件

在keil5里,我如何在一个已经建好的工程里添加新的c和h文件啊? …

查看全部问答>