你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

流程有些混乱,写下来,理一理,也希望朋友们帮指导下。

[复制链接]
any012 提问时间:2016-5-20 15:42 /
悬赏10ST金币已解决
本帖最后由 any012 于 2016-5-20 15:52 编辑

单片机需要做的工作:
1.和ADC芯片通讯,读取AD值,并根据AD值计算成电阻值;
2.参数校准,通过USART1和上位机通讯,走MODBUS协议;
3.和主设备通讯,通过SPI2和主设备通讯,自定义协议。

其中2是产品出厂前调试用的,单片机正常工作情况下,就是读取ADC值,并传给主设备。

分开说。
1.和ADC芯片通讯也是走的SPI,用的是单片机的SPI1,单片机作为主设备。工作方式是这样的,单片机发送条指令,ADC芯片开始采样,采样过程需要一定时间,采样接收后将SPI的MISO引脚拉低通知单片机可以读取数据。单片机再发送SPI命令读取ADC值。然后单片机开始根据设定好的参数将ADC值转化成电阻值。

2.上一步将ADC值计算成电阻值的过程用到的参数,是通过上位机设定的。通过USART1和上位机通讯,走标准MODBUS协议。从网上搜了个STM32用的MODBUS协议,感觉还可以。

3.第一步计算出来的电阻值,最好是要传给主设备的。通过SPI2和主设备相连,我现在做的这个板做SPI从设备。主设备不停的发送SPI读取命令,于是我想用SPI的DMA功能实现。

---------------------------------------

因为一开始是想一步做一步的,功能一点一点的加进来,结果现在的流程很混乱。
于是想写下来理一理。

  1. while(1)
  2. {
  3.     if(Comu_Busy == 0)            //USART1没有接收到据,处于工作状态1或工作状态3
  4.     switch(ad7193DataFlag)        //根据ad7193DataFlag标志,判断工作情况
  5.     {
  6.         case 0x00:              //发送adc读取命令,等待adc采样
  7.             ...
  8.             ad7193DataFlag = 1;
  9.             break;
  10.         case 0x01:              //根据上一次读取的adc值计算电阻值
  11.             ...
  12.             ad7193DataFlag = 2;
  13.             break;
  14.         case 0x02:              //读取adc值或等待
  15.             if(spi1_miso == 0)
  16.             {
  17.                 ...
  18.                 ad7193DataFlag = 0;     //读取spi1_miso状态,如果是低电平,开始读取adc值,然后ad7193DataFlag清零
  19.             }                           //如果spi1_miso是高电平,则ad7193DataFlag仍保持2,继续等待
  20.             break;
  21.     }
  22. }
复制代码

因为发送命令到采样完成可被读取,中间需要一定时间,故在这段时间内计算上次读取的adc值,转化为电阻值。
现在加进去的部分是和主设备的spi通讯部分,用的是spi2,作为从设备,接收用中断,发送用DMA。
现在的尝试是,在上面程序部分的case 0x01里,adc值转化为电阻值后,开启spi2中断,然后在spi2中断函数里,判断帧首,如果接收的数据是帧首,则置个标志,开始接收帧的其他数据,帧长度有限,5个16位数据。如果接受的数据超过5个,则关断spi2中断并置个标志。如果第一个接收的数据不是帧首,也是关断spi2中断。

  1. void SPI2_IRQHandler(void)
  2. {
  3.     spi2Temp = SPI_I2S_ReceiveData(SPI2);
  4.     if(spi2Num == 0)                                        //接收数组未保存任何数据
  5.     {
  6.         if(spi2Temp == 0x3a05)                              //如果数据是帧首
  7.         {
  8.             spi2Num = 1;
  9.             spi2Recive[0] = spi2Temp;
  10.         }
  11.         else
  12.             SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_RXNE, DISABLE);
  13.     }
  14.     else                                                    //已经接收过帧首
  15.     {
  16.         spi2Recive[spi2Num] = spi2Temp;                     //保存剩下帧
  17.         spi2Num++;
  18.         if(spi2Num > 4)                                     //如果超过5个数据
  19.         {
  20.             spi2Num = 0;
  21.             spi2ReciveOk = 1;
  22.             SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_RXNE, DISABLE);
  23.         }
  24.     }
  25.     else
  26.         SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_RXNE, DISABLE);
  27. }
复制代码

现在在修改spi2部分,思维好乱。
之前只读取spi2接收到的5个数据,只判断帧首,然后通过串口发上来,貌似可以。
现在又加进来帧尾的CRC判断,又加了几个标志,然后就不正常了,我脑子也乱了...

最佳答案

查看完整内容

流程不是这样写的,这样充其量只能叫做做什么。流程是从园的开始->园的结束。可以这样理解你的问题: 前两个可以叫做单片机的初始化,可以单独写成一个模块,写出流程来。 后一个是单片机的循环工作——主模块,单独写出来流程来。 流程的基本要领是:先大块——组线条的,而后细化——详细流程[此流程中可以将较为稀的过程填入,可以使代码框],流程有内部一步一步下来的,也有分支,只要是1个模块分支最后都会回到主流程,最后模 ...
收藏 评论1 发布时间:2016-5-20 15:42

举报

1个回答
zhjb1 回答时间:2016-5-20 15:42:59
流程不是这样写的,这样充其量只能叫做做什么。流程是从园的开始->园的结束。可以这样理解你的问题:
前两个可以叫做单片机的初始化,可以单独写成一个模块,写出流程来。
后一个是单片机的循环工作——主模块,单独写出来流程来。
流程的基本要领是:先大块——组线条的,而后细化——详细流程[此流程中可以将较为稀的过程填入,可以使代码框],流程有内部一步一步下来的,也有分支,只要是1个模块分支最后都会回到主流程,最后模块运行结束跳转到那里结束[主流程最后竟如循环或中断]。用文字描述你的流程可以是这样的:
系统初始化->ADC初始化->串口初始化->进入主程序循环。这可以算作主流程。下边以串口初始化为例:
串口初始化模块:串口时钟设置、串口GPIO设置、串口模式设置、串口速率设置、中断[查询]方式设置、DMA设置[缓冲或数组]如果用DMA、开中断或设置查询条件、返回主程序。如果当中还有什么添加进去。
串口还有一个中断[或查询]处理模块,不写了。
如果文字流程没有遗漏,就可以以代码形式添加进去形成你的程序模块,一个一个的模块和跳转或链接构成完整的程序。试试吧

评分

参与人数 1蝴蝶豆 +4 收起 理由
zero99 + 4

查看全部评分

所属标签

相似问题

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版