串口发送数据处理——状态机方式
最近在写GPS接收机向PC机发送数据的程序,GPS接收机每1ms产生一个积分数据,然后由ARM把这个积分数据量化为0和1。为了提高数据发送的效率,这里没有采用每1ms发送一个数据的方式,而是采用块发送的方式,采用ARM的串口发送数据块的中断来实现每次发送8字节的数据,发送8字节后,再在缓冲区读取下一个8字节块。
积分数据量化为0和1后,仅仅需要1bit就可以存储了,在发送的时候,需要把8ms的积分数据拼接成一个字节,然后等待凑够8个字节的最低发送块大小时再发送,也就是说,每64ms才发送一次数据,一次就发送8字节。
笔者的处理方式如下:
采用状态机的方式,每1ms根据当前的状态来完成特定的任务,然后更新下一状态。
这里设计两个状态标志,一个是send_chx_data_state,用来记录8个字节中当前处理的字节状态。
另外一个是bits_count,用来记录当前处理字节中的哪一位。
所达到的效果就是,每1ms把1bit的数据放进8字节中的某一位,当达到64bit时候,进行一次块发送。
程序的代码如下:
View Code
1 uint8 send_chx_data_state = 0; 2 uint8 bits_count = 0; 3 uint8 bits = 0; 4 uint8 bits_tmp = 0; 5 6 void send_chx_data(uint8 chx, uint8 task_enable) 7 { 8 9 if (task_enable) 10 { 11 switch (send_chx_data_state) 12 { 13 case 0: 14 bits_tmp = (chx_data[chx][1] &0x8000) >> 15; 15 bits = bits | (bits_tmp << (7-bits_count)); 16 bits_count++; 17 if (bits_count == 8) 18 { 19 bits_count = 0; 20 chx_send_dat[send_chx_data_state] = bits; 21 bits = 0; 22 send_chx_data_state++; 23 } 24 25 break; 26 case 1: 27 bits_tmp = (chx_data[chx][1] &0x8000) >> 15; 28 bits = bits | (bits_tmp << (7-bits_count)); 29 bits_count++; 30 if (bits_count == 8) 31 { 32 bits_count = 0; 33 chx_send_dat[send_chx_data_state] = bits; 34 bits = 0; 35 send_chx_data_state++; 36 } 37 38 break; 39 case 2: 40 bits_tmp = (chx_data[chx][1] &0x8000) >> 15; 41 bits = bits | (bits_tmp << (7-bits_count)); 42 bits_count++; 43 if (bits_count == 8) 44 { 45 bits_count = 0; 46 chx_send_dat[send_chx_data_state] = bits; 47 bits = 0; 48 send_chx_data_state++; 49 } 50 51 break; 52 case 3: 53 bits_tmp = (chx_data[chx][1] &0x8000) >> 15; 54 bits = bits | (bits_tmp << (7-bits_count)); 55 bits_count++; 56 if (bits_count == 8) 57 { 58 bits_count = 0; 59 chx_send_dat[send_chx_data_state] = bits; 60 bits = 0; 61 send_chx_data_state++; 62 } 63 64 break; 65 case 4: 66 bits_tmp = (chx_data[chx][1] &0x8000) >> 15; 67 bits = bits | (bits_tmp << (7-bits_count)); 68 bits_count++; 69 if (bits_count == 8) 70 { 71 bits_count = 0; 72 chx_send_dat[send_chx_data_state] = bits; 73 bits = 0; 74 send_chx_data_state++; 75 } 76 77 break; 78 case 5: 79 bits_tmp = (chx_data[chx][1] &0x8000) >> 15; 80 bits = bits | (bits_tmp << (7-bits_count)); 81 bits_count++; 82 if (bits_count == 8) 83 { 84 bits_count = 0; 85 chx_send_dat[send_chx_data_state] = bits; 86 bits = 0; 87 send_chx_data_state++; 88 } 89 90 break; 91 case 6: 92 bits_tmp = (chx_data[chx][1] &0x8000) >> 15; 93 bits = bits | (bits_tmp << (7-bits_count)); 94 bits_count++; 95 if (bits_count == 8) 96 { 97 bits_count = 0; 98 chx_send_dat[send_chx_data_state] = bits; 99 bits = 0; 100 send_chx_data_state++; 101 } 102 103 break; 104 case 7: 105 bits_tmp = (chx_data[chx][1] &0x8000) >> 15; 106 bits = bits | (bits_tmp << (7-bits_count)); 107 bits_count++; 108 if (bits_count == 8) 109 { 110 bits_count = 0; 111 chx_send_dat[send_chx_data_state] = bits; 112 uart_send_buffer(p_uart_buffer, (char*)chx_send_dat, 8); 113 bits = 0; 114 send_chx_data_state = 0; 115 } 116 117 break; 118 119 default: 120 break; 121 122 } 123 } 124 else 125 { 126 send_chx_data_state = 0; 127 bits_count = 0; 128 } 129 }
程序每1ms执行一次,每次获取GPS接收机的积分数据并取其最高位,然后把最高位按先后顺序放到一个字节中的每一位。
总体上,代码量较大,但理解和处理起来非常简洁明了,充分发挥了状态机的优势。
下面带来一个更恐怖的,发送的是8个通道的数据,每次读取8个通道的数据并拼接成一个字节,对于每个数据位,没有采用for循环语句,而是直接展开。
当达到8个字节是,再进行发送,因此看起来代码量很恐怖,但其实执行效率是非常高的,而且每个状态中的大部分代码都是相同的。
View Code
1 uint8 send_multi_state = 0; 2 3 void send_multi_chx_data(uint8 *chx, uint8 task_enable) 4 { 5 uint8 chx_tmp = 0; 6 if (task_enable) 7 { 8 switch (send_multi_state) 9 { 10 case 0: 11 bits_tmp = (chx_data[chx[0]][1] &0x8000) >> 15; 12 bits = bits | (bits_tmp << (7)); 13 bits_tmp = (chx_data[chx[1]][1] &0x8000) >> 15; 14 bits = bits | (bits_tmp << (6)); 15 bits_tmp = (chx_data[chx[2]][1] &0x8000) >> 15; 16 bits = bits | (bits_tmp << (5)); 17 bits_tmp = (chx_data[chx[3]][1] &0x8000) >> 15; 18 bits = bits | (bits_tmp << (4)); 19 bits_tmp = (chx_data[chx[4]][1] &0x8000) >> 15; 20 bits = bits | (bits_tmp << (3)); 21 bits_tmp = (chx_data[chx[5]][1] &0x8000) >> 15; 22 bits = bits | (bits_tmp << (2)); 23 bits_tmp = (chx_data[chx[6]][1] &0x8000) >> 15; 24 bits = bits | (bits_tmp << (1)); 25 bits_tmp = (chx_data[chx[7]][1] &0x8000) >> 15; 26 bits = bits | (bits_tmp << (0)); 27 28 chx_send_dat[send_multi_state] = bits; 29 send_multi_state++; 30 break; 31 case 1: 32 bits_tmp = (chx_data[chx[0]][1] &0x8000) >> 15; 33 bits = bits | (bits_tmp << (7)); 34 bits_tmp = (chx_data[chx[1]][1] &0x8000) >> 15; 35 bits = bits | (bits_tmp << (6)); 36 bits_tmp = (chx_data[chx[2]][1] &0x8000) >> 15; 37 bits = bits | (bits_tmp << (5)); 38 bits_tmp = (chx_data[chx[3]][1] &0x8000) >> 15; 39 bits = bits | (bits_tmp << (4)); 40 bits_tmp = (chx_data[chx[4]][1] &0x8000) >> 15; 41 bits = bits | (bits_tmp << (3)); 42 bits_tmp = (chx_data[chx[5]][1] &0x8000) >> 15; 43 bits = bits | (bits_tmp << (2)); 44 bits_tmp = (chx_data[chx[6]][1] &0x8000) >> 15; 45 bits = bits | (bits_tmp << (1)); 46 bits_tmp = (chx_data[chx[7]][1] &0x8000) >> 15; 47 bits = bits | (bits_tmp << (0)); 48 49 chx_send_dat[send_multi_state] = bits; 50 send_multi_state++; 51 break; 52 case 2: 53 bits_tmp = (chx_data[chx[0]][1] &0x8000) >> 15; 54 bits = bits | (bits_tmp << (7)); 55 bits_tmp = (chx_data[chx[1]][1] &0x8000) >> 15; 56 bits = bits | (bits_tmp << (6)); 57 bits_tmp = (chx_data[chx[2]][1] &0x8000) >> 15; 58 bits = bits | (bits_tmp << (5)); 59 bits_tmp = (chx_data[chx[3]][1] &0x8000) >> 15; 60 bits = bits | (bits_tmp << (4)); 61 bits_tmp = (chx_data[chx[4]][1] &0x8000) >> 15; 62 bits = bits | (bits_tmp << (3)); 63 bits_tmp = (chx_data[chx[5]][1] &0x8000) >> 15; 64 bits = bits | (bits_tmp << (2)); 65 bits_tmp = (chx_data[chx[6]][1] &0x8000) >> 15; 66 bits = bits | (bits_tmp << (1)); 67 bits_tmp = (chx_data[chx[7]][1] &0x8000) >> 15; 68 bits = bits | (bits_tmp << (0)); 69 70 chx_send_dat[send_multi_state] = bits; 71 send_multi_state++; 72 break; 73 case 3: 74 bits_tmp = (chx_data[chx[0]][1] &0x8000) >> 15; 75 bits = bits | (bits_tmp << (7)); 76 bits_tmp = (chx_data[chx[1]][1] &0x8000) >> 15; 77 bits = bits | (bits_tmp << (6)); 78 bits_tmp = (chx_data[chx[2]][1] &0x8000) >> 15; 79 bits = bits | (bits_tmp << (5)); 80 bits_tmp = (chx_data[chx[3]][1] &0x8000) >> 15; 81 bits = bits | (bits_tmp << (4)); 82 bits_tmp = (chx_data[chx[4]][1] &0x8000) >> 15; 83 bits = bits | (bits_tmp << (3)); 84 bits_tmp = (chx_data[chx[5]][1] &0x8000) >> 15; 85 bits = bits | (bits_tmp << (2)); 86 bits_tmp = (chx_data[chx[6]][1] &0x8000) >> 15; 87 bits = bits | (bits_tmp << (1)); 88 bits_tmp = (chx_data[chx[7]][1] &0x8000) >> 15; 89 bits = bits | (bits_tmp << (0)); 90 91 chx_send_dat[send_multi_state] = bits; 92 send_multi_state++; 93 94 break; 95 case 4: 96 bits_tmp = (chx_data[chx[0]][1] &0x8000) >> 15; 97 bits = bits | (bits_tmp << (7)); 98 bits_tmp = (chx_data[chx[1]][1] &0x8000) >> 15; 99 bits = bits | (bits_tmp << (6)); 100 bits_tmp = (chx_data[chx[2]][1] &0x8000) >> 15; 101 bits = bits | (bits_tmp << (5)); 102 bits_tmp = (chx_data[chx[3]][1] &0x8000) >> 15; 103 bits = bits | (bits_tmp << (4)); 104 bits_tmp = (chx_data[chx[4]][1] &0x8000) >> 15; 105 bits = bits | (bits_tmp << (3)); 106 bits_tmp = (chx_data[chx[5]][1] &0x8000) >> 15; 107 bits = bits | (bits_tmp << (2)); 108 bits_tmp = (chx_data[chx[6]][1] &0x8000) >> 15; 109 bits = bits | (bits_tmp << (1)); 110 bits_tmp = (chx_data[chx[7]][1] &0x8000) >> 15; 111 bits = bits | (bits_tmp << (0)); 112 113 chx_send_dat[send_multi_state] = bits; 114 send_multi_state++; 115 break; 116 case 5: 117 bits_tmp = (chx_data[chx[0]][1] &0x8000) >> 15; 118 bits = bits | (bits_tmp << (7)); 119 bits_tmp = (chx_data[chx[1]][1] &0x8000) >> 15; 120 bits = bits | (bits_tmp << (6)); 121 bits_tmp = (chx_data[chx[2]][1] &0x8000) >> 15; 122 bits = bits | (bits_tmp << (5)); 123 bits_tmp = (chx_data[chx[3]][1] &0x8000) >> 15; 124 bits = bits | (bits_tmp << (4)); 125 bits_tmp = (chx_data[chx[4]][1] &0x8000) >> 15; 126 bits = bits | (bits_tmp << (3)); 127 bits_tmp = (chx_data[chx[5]][1] &0x8000) >> 15; 128 bits = bits | (bits_tmp << (2)); 129 bits_tmp = (chx_data[chx[6]][1] &0x8000) >> 15; 130 bits = bits | (bits_tmp << (1)); 131 bits_tmp = (chx_data[chx[7]][1] &0x8000) >> 15; 132 bits = bits | (bits_tmp << (0)); 133 134 chx_send_dat[send_multi_state] = bits; 135 send_multi_state++; 136 break; 137 case 6: 138 bits_tmp = (chx_data[chx[0]][1] &0x8000) >> 15; 139 bits = bits | (bits_tmp << (7)); 140 bits_tmp = (chx_data[chx[1]][1] &0x8000) >> 15; 141 bits = bits | (bits_tmp << (6)); 142 bits_tmp = (chx_data[chx[2]][1] &0x8000) >> 15; 143 bits = bits | (bits_tmp << (5)); 144 bits_tmp = (chx_data[chx[3]][1] &0x8000) >> 15; 145 bits = bits | (bits_tmp << (4)); 146 bits_tmp = (chx_data[chx[4]][1] &0x8000) >> 15; 147 bits = bits | (bits_tmp << (3)); 148 bits_tmp = (chx_data[chx[5]][1] &0x8000) >> 15; 149 bits = bits | (bits_tmp << (2)); 150 bits_tmp = (chx_data[chx[6]][1] &0x8000) >> 15; 151 bits = bits | (bits_tmp << (1)); 152 bits_tmp = (chx_data[chx[7]][1] &0x8000) >> 15; 153 bits = bits | (bits_tmp << (0)); 154 155 chx_send_dat[send_multi_state] = bits; 156 send_multi_state++; 157 break; 158 case 7: 159 bits_tmp = (chx_data[chx[0]][1] &0x8000) >> 15; 160 bits = bits | (bits_tmp << (7)); 161 bits_tmp = (chx_data[chx[1]][1] &0x8000) >> 15; 162 bits = bits | (bits_tmp << (6)); 163 bits_tmp = (chx_data[chx[2]][1] &0x8000) >> 15; 164 bits = bits | (bits_tmp << (5)); 165 bits_tmp = (chx_data[chx[3]][1] &0x8000) >> 15; 166 bits = bits | (bits_tmp << (4)); 167 bits_tmp = (chx_data[chx[4]][1] &0x8000) >> 15; 168 bits = bits | (bits_tmp << (3)); 169 bits_tmp = (chx_data[chx[5]][1] &0x8000) >> 15; 170 bits = bits | (bits_tmp << (2)); 171 bits_tmp = (chx_data[chx[6]][1] &0x8000) >> 15; 172 bits = bits | (bits_tmp << (1)); 173 bits_tmp = (chx_data[chx[7]][1] &0x8000) >> 15; 174 bits = bits | (bits_tmp << (0)); 175 176 chx_send_dat[send_multi_state] = bits; 177 178 uart_send_buffer(p_uart_buffer, (char*)chx_send_dat, 8); 179 send_multi_state = 0; 180 break; 181 default: 182 break; 183 184 } 185 } 186 else 187 { 188 send_multi_state = 0; 189 } 190 }