您的位置:首页 > 编程语言

用于单片机编程的一种简单的主函数框架

2018-09-27 13:49 211 查看

常见的单片机最小系统(最小外围电路)中,会带有单片机、晶振、LDO、按键、LED指示灯。假如是使用STM32,现在通常会配合STM32CubeMX,快速生成初始化代码和工程项目文件。在生成了一套工程项目后,需要在文件的特定位置加上用户代码。

我对操作系统编程不熟悉,但需要把单片机对外扩模块的操作程序编成任务,每个任务在一秒钟内执行的次数不同。因此需要编个简单的框架,控制每个任务的执行次数。

[code]/* Private variables ---------------------------------------------------------*/
uint32_t counter_10ms, counter_50ms, counter_100ms, counter_500ms, counter_1000ms, counter_2000ms, counter_3s, counter_5s, counter_10s, counter_20s, counter_50s;
uint8_t flag_1ms, flag_10ms, flag_50ms, flag_100ms, flag_500ms, flag_1000ms, flag_2000ms, flag_3s, flag_5s, flag_10s, flag_20s, flag_50s;

int main(void)
{
//这里执行初始化代码
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)  {
if(flag_1ms ==1)	{
LEDSoftTimer(b_LED1Freq, b_LED1Duty, b_LED2Freq, b_LED2Duty);
flag_1ms = 0;

if(flag_ADCbusy==RESET)		{
ADC_GetData();
flag_ADCbusy = SET;
if (HAL_ADC_Start_DMA(&hadc1, (uint32_t *)a_ADCxConvertedValues,   2) != HAL_OK)			{
Error_Handler();
}
}
}
if(flag_10ms==1)	{
flag_10ms=0;
}
if(flag_50ms==1)	{
flag_50ms=0;
}
if(flag_100ms==1)	{
flag_100ms=0;
SerialDisplay();
}
if(flag_500ms==1)	{
flag_500ms=0;
}
if(flag_1000ms==1)	{
flag_1000ms=0;
sec++;
if(sec>0xff)
sec = 0;
}
if(flag_2000ms==1)	{
flag_2000ms=0;
}
if(flag_3s==1)	{
flag_3s=0;
}
if(flag_5s==1)	{
flag_5s=0;
}
if(flag_10s==1)	{
flag_10s=0;
}
if(flag_20s==1)	{
flag_20s=0;
}
if(flag_50s==1)	{
flag_50s=0;
}
}
/* USER CODE END 3 */

}
//然后在systick中更新时间计数器和相关flag的值,systick中断由CPU定时器生成,每1ms中断一次
void HAL_SYSTICK_Callback(void)
{

flag_1ms = 1;
/*update counters*/
if(counter_10ms<9) {
counter_10ms++;
}
else {
counter_10ms = 0;
flag_10ms = 1;
}

if(counter_50ms<49)	{
counter_50ms++;
} else {
counter_50ms = 0;
flag_50ms = 1;
}

if(counter_100ms<99) {
counter_100ms++;
}	else {
counter_100ms = 0;
flag_100ms = 1;
if(counter_500ms<4)	{
counter_500ms++;
}	else {
counter_500ms = 0;
flag_500ms = 1;
}
if(counter_1000ms<9) {
counter_1000ms++;
}	else {
counter_1000ms = 0;
flag_1000ms = 1;
UpdateDateTime();
if(counter_3s < 2) {
counter_3s++;
}	else {
counter_3s = 0;
flag_3s = 1;
}
if(counter_5s < 4) {
counter_5s++;
}	else {
counter_5s = 0;
flag_5s = 1;
}
if(counter_10s < 9)	{
counter_10s++;
}	else {
counter_10s = 0;
flag_10s = 1;
}
}
if(counter_2000ms<19)	{
counter_2000ms++;
}	else {
counter_2000ms = 0;
flag_2000ms = 1;
}
}
}

上面的程序中,每1ms执行一次ADC采样。还有每100ms执行一次程序把数据传输到上位机显示。直接把上面的代码复制到STM32CubeMX生成的项目文件,即可快速的分配CPU运算资源。

另外,最简单的状态机编程结构如下。

本例子用STM32和NodeMCU通信,驱动NodeMCU和手机连接,并通过TCP协议把一句句的信息传输到手机。

[code]void Proc_NodeMCU(void)
{
uint8_t CIPSEND_CustomSize[2];
uint8_t NodeMCU_ACK_res;
if(Status_NodeMCU == 1)
{

清空UART接收数据
发送AT指令
采用阻塞,超时的方式检查NodeMCU有没回传"OK\r\n"字符,
如果收到"OK\r\n": Status_NodeMCU=2;且flag_ProcNodeMCUActive=1;代表NodeMCU程序有效
否则无NodeMCU连接
}
else if(Status_NodeMCU == 2)
{
清空UART接收数据
发送AT指令配置成STATION模式
采用阻塞,超时的方式检查NodeMCU有没回传"OK\r\n"字符,
如果收到"OK\r\n": Status_NodeMCU=3;
}
else if(Status_NodeMCU == 3)
{
清空UART接收数据
发送AT指令,控制NodeMCU连接AP
采用阻塞,超时的方式检查NodeMCU有没回传"OK\r\n"字符,
如果收到"OK\r\n": Status_NodeMCU=4;
}
else if(Status_NodeMCU == 4)
{
清空UART接收数据
发送AT指令,NodeMCU和手机建立TCP连接
处理回传数据
如果正常:Status_NodeMCU=10;
}
else if(Status_NodeMCU == 10)
{
清空UART接收数据
发送AT指令,控制NodeMCU进入数据透传模式,并发送信息包至手机
处理回传数据
如果正常:Status_NodeMCU=11;
如果不正常:Status_NodeMCU=4;将重新连接

}
else if(Status_NodeMCU == 11)
{
清空UART接收数据
发送AT指令控制NodeMCU进入低功率发送模式,减少射频干扰和功耗
Status_NodeMCU = 10;下次执行本程序可省去连接部分,直接控制NodeMCU进入数据透传模式
本次发送数据完成,flag_ProcNodeMCUActive=0;
}
else
{
Status_NodeMCU = 1;
}

}

还有一种状态机写法,

状态机的两种写法对比

TI官方代码中的任务状态机

阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐