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

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

[复制链接]
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管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版