[英]Main function's command repetition problem in C
I'm Noh.我是诺
I'm trying to control Microcontroller with C code.我正在尝试使用 C 代码控制微控制器。 And I'm using a code I got from GitHub. (Here's the link https://github.com/jwr/msp430_usi_i2c )
我正在使用从 GitHub 获得的代码。(这是链接https://github.com/jwr/msp430_usi_i2c )
I encountered the problem that main function doesn't stop.我遇到了main function不停的问题。 Even though there's no loop command in main, command flow repeats again and again.
即使在 main 中没有循环命令,命令流也会一次又一次地重复。
I write command flow like below.我写的命令流程如下。
Write 00 → Write AF → Write 00 → Write 05 → Write 45 → Write 40 → Write 03 → Write B0 → Read EE写00→写AF→写00→写05→写45→写40→写03→写B0→读EE
And you can see the command flow repeats from beginning to end.您可以看到命令流从头到尾重复。
Please refer to below code and the communication result.请参考下面的代码和通信结果。
#include <msp430.h>
#include <stdint.h>
#include "usi_i2c.h"
#include <stdio.h>
#include <stdlib.h>
// Internal state
static uint16_t const *i2c_sequence;
static uint16_t i2c_sequence_length;
static uint8_t *i2c_receive_buffer;
static uint16_t i2c_wakeup_sr_bits;
i2c_state_type i2c_state = I2C_IDLE;
static uint8_t status;
static inline void i2c_prepare_stop();
static inline void i2c_prepare_data_xmit_recv();
void i2c_send_sequence(uint16_t const * sequence,
uint16_t sequence_length,
uint8_t *received_data,
uint16_t wakeup_sr_bits) {
while(i2c_state != I2C_IDLE); // we can't start another sequence until the current one is done
while((status==0xEE)|(status==0xEF)) P1OUT |= 0x01;
P1OUT &= ~0x01;
i2c_sequence = sequence;
i2c_sequence_length = sequence_length;
i2c_receive_buffer = received_data;
i2c_wakeup_sr_bits = wakeup_sr_bits;
i2c_state = I2C_START;
USICTL1 |= USIIFG; // actually start communication
}
static inline void i2c_prepare_stop() {
USICTL0 |= USIOE; // SDA = output
USISRL = 0x00;
USICNT |= 0x01; // Bit counter= 1, SCL high, SDA low
i2c_state = I2C_STOP;
}
static inline void i2c_prepare_data_xmit_recv() {
if(i2c_sequence_length == 0) {
i2c_prepare_stop(); // nothing more to do, prepare to send STOP
} else {
if(*i2c_sequence == I2C_RESTART) {
USICTL0 |= USIOE; // SDA = output
USISRL = 0xff; // prepare and send a dummy bit, so that SDA is high
USICNT = (USICNT & 0xE0) | 1;
i2c_state = I2C_START;
}
else if(*i2c_sequence == I2C_READ) {
USICTL0 &= ~USIOE; // SDA = input
USICNT = (USICNT & 0xE0) | 8; // Bit counter = 8, RX data
i2c_state = I2C_RECEIVED_DATA; // next state: Test data and ACK/NACK
} else { // a write
(*i2c_sequence >> 8) == 0
USICTL0 |= USIOE; // SDA = output
USISRL = (char)(*i2c_sequence); // Load data byte
USICNT = (USICNT & 0xE0) | 8; // Bit counter = 8, start TX
i2c_state = I2C_PREPARE_ACKNACK; // next state: prepare to receive data ACK/NACK
}
i2c_sequence++;
i2c_sequence_length--;
}
}
#ifdef __GNUC__
__attribute__((interrupt(USI_VECTOR)))
#else
#pragma vector = USI_VECTOR
__interrupt
#endif
void USI_TXRX(void)
{
switch(__even_in_range(i2c_state,12)) {
case I2C_IDLE:
break;
case I2C_START: // generate start condition
USISRL = 0x00;
USICTL0 |= (USIGE|USIOE);
USICTL0 &= ~USIGE;
i2c_prepare_data_xmit_recv();
break;
case I2C_PREPARE_ACKNACK: // prepare to receive ACK/NACK
USICTL0 &= ~USIOE; // SDA = input
USICNT |= 0x01; // Bit counter=1, receive (N)Ack bit into USISRL
i2c_state = I2C_HANDLE_RXTX; // Go to next state: check ACK/NACK and
continue xmitting/receiving if necessary
break;
case I2C_HANDLE_RXTX: // Process Address Ack/Nack & handle data TX
if((USISRL & BIT0) != 0) { // did we get a NACK?
i2c_prepare_stop();
} else {
i2c_prepare_data_xmit_recv();
}
break;
case I2C_RECEIVED_DATA: // received data, send ACK/NACK
*i2c_receive_buffer = USISRL;
i2c_receive_buffer++;
USICTL0 |= USIOE; // SDA = output
if(i2c_sequence_length > 0) {
// If this is not the last byte
USISRL = 0x00; // ACK
i2c_state = I2C_HANDLE_RXTX; // Go to next state: data/rcv again
} else { // last byte: send NACK
USISRL = 0xff; // NACK
i2c_state = I2C_PREPARE_STOP; // stop condition is next
}
USICNT |= 0x01; // Bit counter = 1, send ACK/NACK bit
break;
case I2C_PREPARE_STOP: // prepare stop condition
i2c_prepare_stop(); // prepare stop, go to state 14 next
break;
case I2C_STOP: // Generate Stop Condition
USISRL = 0x0FF; // USISRL = 1 to release SDA
USICTL0 |= USIGE; // Transparent latch enabled
USICTL0 &= ~(USIGE|USIOE); // Latch/SDA output disabled
i2c_state = I2C_IDLE; // Reset state machine for next xmt
if(i2c_wakeup_sr_bits) {
_bic_SR_register_on_exit(i2c_wakeup_sr_bits); // exit active if prompted to
}
break;
}
USICTL1 &= ~USIIFG; // Clear pending flag
}
void main(){
i2c_init(USIDIV_5, USISSEL_2);
uint16_t PUP[] = {0xEA, 0x00};
uint16_t PDWN[] = {0xEA, 0x20};
uint16_t CVOL_PowerUp[] = {0xEA, 0xAF, 0x00};
uint16_t AMODE_PowerUp[] = {0xEA, 0x05, 0x45};
uint16_t AMODE_PowerDown[] = {0xEA, 0x05, 0x41};
uint16_t RDSTAT_Command[] = {0xEA, 0xB0};
uint16_t RDSTAT_Read[] = {0xEB, I2C_READ};
uint16_t START[] = {0xEA, 0x51};
uint16_t PLAY[] = {0xEA, 0x40, 0x03};
uint16_t STOP[] = {0xEA, 0x61};
i2c_send_sequence(PUP, 2, &status, LPM0_bits); // 00
i2c_send_sequence(CVOL_PowerUp, 3, &status, LPM0_bits); // AF 00
i2c_send_sequence(AMODE_PowerUp, 3, &status, LPM0_bits); // 05 45
i2c_send_sequence(PLAY, 3, &status, LPM0_bits); // 40 03
i2c_send_sequence(RDSTAT_Command, 2, &status, LPM0_bits); // B0
i2c_send_sequence(RDSTAT_Read, 2, &status, LPM0_bits);
}
void i2c_init(uint16_t usi_clock_divider, uint16_t usi_clock_source) {
_disable_interrupts();
USICTL0 = USIPE6|USIPE7|USIMST|USISWRST; // Port & USI mode setup
USICTL1 = USII2C|USIIE; // Enable I2C mode & USI interrupt
USICKCTL = usi_clock_divider | usi_clock_source | USICKPL;
USICNT |= USIIFGCC; // Disable automatic clear control
USICTL0 &= ~USISWRST; // Enable USI
USICTL1 &= ~USIIFG; // Clear pending flag
_enable_interrupts();
P1OUT = 0xC0; // P1.6 & P1.7 Pullups, others to 0
P1REN |= 0xC0; // P1.6 & P1.7 Pullups
P1DIR = 0xFF; // Unused pins as outputs
P2OUT = 0;
P2DIR = 0xFF;
}
This is code run result gotten by using Beagle(communication data recorder), and I believe you can see command flow is repeating (from 'Write 00' to 'Read EE')这是使用 Beagle(通信数据记录器)得到的代码运行结果,我相信你可以看到命令流在重复(从'Write 00'到'Read EE')
I have no idea why main function repeats without any loop function.我不知道为什么主 function 没有任何循环 function 重复。
I want this code run main function's command flow only once.我希望这段代码只运行一次主函数的命令流。
Do you happen to know why this happens and how to resolve this problem?您碰巧知道为什么会发生这种情况以及如何解决这个问题吗?
Thank you!谢谢!
Sincerely Noh真诚的能
Most programs for a microcontroller have some assembly language initialisation code that does some basic configuration of the MCU, copies the data section from flash to RAM, zeros the.bss, then jumps to main().大多数微控制器程序都有一些汇编语言初始化代码,这些代码对 MCU 进行一些基本配置,将数据部分从 flash 复制到 RAM,将 the.bss 清零,然后跳转到 main()。
Typically, main() would never return.通常,main() 永远不会返回。 It would consist of an infinite loop, doing whatever tasks the software is meant to do, forever, until power is removed.
它将由一个无限循环组成,永远执行软件打算执行的任何任务,直到电源被移除。
So your code returning is not very typical.所以你的代码返回不是很典型。 What is the MCU meant to do if main() returns?
如果 main() 返回,MCU 打算做什么? It has nothing else to run.
它没有其他可运行的。 Some options for it might be to:
它的一些选择可能是:
It sounds like, in your case, either 2 or 3 is happening.在您的情况下,这听起来像是 2 或 3 正在发生。
If you want your code to just stop after it has done its thing, add an empty infinite loop at the end of main():如果你想让你的代码在完成它的事情后就停止,在 main() 的末尾添加一个空的无限循环:
for (;;)
;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.